Selenium3框架详解

2024-03-26 00:38
文章标签 详解 框架 selenium3

本文主要是介绍Selenium3框架详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

自从17年开始就不再怎么关注UI自动化测试了,也就很少关注Selenium的知识体系,在当时的背景和环境下有很多的思考和选择点,基于UI的自动化测试并不是所有的场合下都使用它合适,任何一个技术,要把它应用在合适的场景下才能够显示出它的最大的价值。今天这里就简单的对Page Objects做一个介绍。

基于UI的自动化测试的痛点在于如何可以高效的维护并且满足业务迭代的需求,或者说这是自动化测试的基本诉求,高效,维护方便,能够提升测试效率,从而带来研发效率的提升,最大达到工程效率的提升。

在UI自动化测试中,产品的快速迭代,导致页面元素的属性经常变来变去,另外一点是数据如何分离,和大批量的自动化测试用例如何可以在很短的时间范围内执行完成并且给出比较权威的测试报告,能够反馈出覆盖到的所测试产品的产品质量,从而给管理者带来有价值的信息。

坦白说,这个过程是复杂的,做不代表就存在价值,但是存在就是合理,合理不代表就是正确,所以就有了持续不断的优化和持续改进的过程。

基于页面对象设计模式存在这么几个优点,主要是:

1、创建可以跨多个测试用例共享的代码

2、减少重复代码执行的数量

3、如果用户界面发生变化后,只需要在一个地方维护就可以了

那么基于如上的思想,是否能够写一个框架来达到这样的一个诉求了?另外一点比较困难的是在元素定位中存在8种方法,如何进行整合。在看Appium源码的时候,Appium中元素定位的类MobilyBy,见它的源码:

from selenium.webdriver.common.by import By
class MobileBy(By):    IOS_PREDICATE = '-ios predicate string'    IOS_UIAUTOMATION = '-ios uiautomation'    IOS_CLASS_CHAIN = '-ios class chain'    ANDROID_UIAUTOMATOR = '-android uiautomator'    ANDROID_VIEWTAG = '-android viewtag'    ANDROID_DATA_MATCHER = '-android datamatcher'    ACCESSIBILITY_ID = 'accessibility id'    IMAGE = '-image'    CUSTOM = '-custom'
在如上的源码中,让人惊喜的是看到了By类,也就是说MobileBy类继承了By
类,这也就意味着完全可以把Selenium和Appium整合起来,特别是在元素定
位的部分,但是依然存在任何把这么多的元素定位的方法整合起来,在Selenium
的源码的WebElement类中,存在方法find_element,在该方法中可以看到对元
素各个属性的判断,见源码:
def find_element(self, by=By.ID, value=None):    """    Find an element given a By strategy and locator. Prefer the find_element_by_* methods when    possible.    :Usage:        element = element.find_element(By.ID, 'foo')    :rtype: WebElement    """    if self._w3c:        if by == By.ID:            by = By.CSS_SELECTOR            value = '[id="%s"]' % value        elif by == By.TAG_NAME:            by = By.CSS_SELECTOR        elif by == By.CLASS_NAME:            by = By.CSS_SELECTOR            value = ".%s" % value        elif by == By.NAME:            by = By.CSS_SELECTOR            value = '[name="%s"]' % value    return self._execute(Command.FIND_CHILD_ELEMENT,                         {"using": by, "value": value})['value']
基于如上的源码,可以得到,关于元素属性的整合可以使用find_element
方法来完成,那么关于如何Selenium和Appium,可以使用工厂设计模式
来完成这个整合的任务,基于如上的分析,编写一个工厂类,编写工厂方法
,创造对应的实例来达到要测试的产品到底是WEB还是APP,编写基础类
base.py,它的源码:
#!/usr/bin/env python#coding:utf-8 #Author:无涯from selenium import  webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.expected_conditions import NoSuchElementExceptionfrom selenium.webdriver.support.wait import WebDriverWaitfrom appium import  webdriverfrom appium.webdriver.common.mobileby import MobileBy
class Factory(object):   def __init__(self,driver):      self.driver=driver   def createDriver(self,driver):      '''工厂方法'''      if driver=='web':         return WebUi(self.driver)      elif driver=='app':         return AppUi(self.driver)
class WebDriver():   def __init__(self,driver):      self.driver=driver   def findElement(self,*loc):      try:         return WebDriverWait(self.driver,20).until(            lambda x:x.find_element(*loc))      except NoSuchElementException as e:         print(e.args[0])def findElements(self,*loc):      try:         return WebDriverWait(self.driver,20).until(            lambda x:x.find_elements(*loc))      except NoSuchElementException as e:         print(e.args[0])
class WebUi(WebDriver):   def __str__(self):      return 'WebUi'class AppUi(WebDriver):   def __str__(self):      return 'AppUi'
注释:在上面的代码中,在Factory类中定义了工厂类,Factory类生成
WebDriver对象。定义Factory类创建不同的WebDriver对象。WebUI
类和AppUI类继承自WebDriver类,WebUI和AppUI可以看作是具体的
测试对象产品(Web和App)。在Factory类中定义了工厂方法createDriver,工具字符串类型driver的值,
生成不同的WebDriver对象。如果driver对象是“web”,则调用WebUI,
返回WebUI类的实例。如果driver对象是“app”,则调用AppUI,返回
AppUI类的实例。

解决了如上的问题后,下来的代码相对来说比较好写,在对象层中继承WebUi或者AppUi,然后定位元素属性,编写对应的方法,这里以百度搜索为案例,在百度搜索输入框输入搜索的关键字,并且获取到这个关键字,使用到的方法是get_attribute(),创建模块baidu.py,它的源码为:

#!/usr/bin/env python#coding:utf-8 #Author:无涯from base.base import *from selenium.webdriver.common.by import By
class Baidu(WebUi):   so_loc=(By.ID,'kw')def typeSo(self,keyword):      '''百度搜索输入框输入关键字'''      self.findElement(*self.so_loc).send_keys(keyword)def getKeyword(self):      '''返回输入的搜索关键字'''      return self.findElement(*self.so_loc).get_attribute('value')
接下来在测试层编写具体的测试代码,但是测试固件要分离,在之前的文章
中也介绍过这部分,我今晚再解释下,在每一个测试模块的测试类中,都需
要继承unittest模块中的TestCase,在测试固件中需要初始化Webdriver
,和指定要测试的浏览器,测试地址,打开浏览器和关闭浏览器的操作,问
题是一个系统的测试会编写很多的测试模块以及测试类,如果需要在测试的浏览器由Chrome替换为Firefox,或者测试地址由A变为B,那么需要在测
试测试固件中来修改测试地址,和指定要测试的浏览器,利用继承的思想,
把测试固件分离后,只需要修改一个地方即可,在对象层增加模块init.py,
编写类分离测试固件,见这部分的源码:
#!/usr/bin/env python#coding:utf-8 #Author:无涯import  unittestfrom selenium import  webdriver
class  Init(unittest.TestCase):   def setUp(self):      self.driver = webdriver.Chrome()      self.driver.maximize_window()      self.driver.implicitly_wait(30)      self.driver.get('http://www.baidu.com')def tearDown(self):      self.driver.quit()
下来就是测试具体的测试用例,在tests包下创建测试模块,编写测试类,
继承测试固件的类和对象层的类,同时编写的测试用例一定要加断言,没有
断言的自动化测试用例是无效的,测试用例这部分代码简单,搜索关键字,
获取搜索的关键字,然后断言验证它,它的源码为:
#!/usr/bin/env python#coding:utf-8 #Author:无涯import  unittestfrom page.baidu import Baidufrom page.init import  Initclass BaiduTest(Init,Baidu):   def test_baidu_so(self):      '''测试:获取搜索的关键字并且验证它'''      self.typeSo('无涯')      self.assertEqual(self.getKeyword(),'无涯')
if __name__ == '__main__':    unittest.main(verbosity=2)
如上代码执行后的结果为:

接下来是UI自动化测试中测试数据的分离,这部分后面再详解。关于UI的自动化测试,目前应用的场景可能在快速迭代的产品中应用不是很合适,但是在一些比较稳定的产品,发展周期比较长使用它还是存在很大的价值。

脚本:无涯

图片:无涯

来源:无涯


 / END.

猪圈子

微信号:shichaogg

推荐理由:

致力于python爬虫系列及其他python相关经典好文集中地,以及程序员娱乐生活圈趣事分享(小编从业测试岗位四年SAAS平台+一年电商平台测试相关工作)积极分享趣事的90后免费领取学习资料 ,关注后,后台回复"抓包"测试"python"

▼长按下方↓↓↓二维码识别关注

搜索微信:shichaogg 

部分图片来源于网络,如有侵权请联系小编删除


分享他人在看↓↓

这篇关于Selenium3框架详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/846786

相关文章

Python异步编程之await与asyncio基本用法详解

《Python异步编程之await与asyncio基本用法详解》在Python中,await和asyncio是异步编程的核心工具,用于高效处理I/O密集型任务(如网络请求、文件读写、数据库操作等),接... 目录一、核心概念二、使用场景三、基本用法1. 定义协程2. 运行协程3. 并发执行多个任务四、关键

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Java利用@SneakyThrows注解提升异常处理效率详解

《Java利用@SneakyThrows注解提升异常处理效率详解》这篇文章将深度剖析@SneakyThrows的原理,用法,适用场景以及隐藏的陷阱,看看它如何让Java异常处理效率飙升50%,感兴趣的... 目录前言一、检查型异常的“诅咒”:为什么Java开发者讨厌它1.1 检查型异常的痛点1.2 为什么说

MySQL的配置文件详解及实例代码

《MySQL的配置文件详解及实例代码》MySQL的配置文件是服务器运行的重要组成部分,用于设置服务器操作的各种参数,下面:本文主要介绍MySQL配置文件的相关资料,文中通过代码介绍的非常详细,需要... 目录前言一、配置文件结构1.[mysqld]2.[client]3.[mysql]4.[mysqldum

springboot2.1.3 hystrix集成及hystrix-dashboard监控详解

《springboot2.1.3hystrix集成及hystrix-dashboard监控详解》Hystrix是Netflix开源的微服务容错工具,通过线程池隔离和熔断机制防止服务崩溃,支持降级、监... 目录Hystrix是Netflix开源技术www.chinasem.cn栈中的又一员猛将Hystrix熔

Java调用Python脚本实现HelloWorld的示例详解

《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、

python之uv使用详解

《python之uv使用详解》文章介绍uv在Ubuntu上用于Python项目管理,涵盖安装、初始化、依赖管理、运行调试及Docker应用,强调CI中使用--locked确保依赖一致性... 目录安装与更新standalonepip 安装创建php以及初始化项目依赖管理uv run直接在命令行运行pytho

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.

MySQL中REPLACE函数与语句举例详解

《MySQL中REPLACE函数与语句举例详解》在MySQL中REPLACE函数是一个用于处理字符串的强大工具,它的主要功能是替换字符串中的某些子字符串,:本文主要介绍MySQL中REPLACE函... 目录一、REPLACE()函数语法:参数说明:功能说明:示例:二、REPLACE INTO语句语法:参数

redis数据结构之String详解

《redis数据结构之String详解》Redis以String为基础类型,因C字符串效率低、非二进制安全等问题,采用SDS动态字符串实现高效存储,通过RedisObject封装,支持多种编码方式(如... 目录一、为什么Redis选String作为基础类型?二、SDS底层数据结构三、RedisObject