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

相关文章

Debezium 与 Apache Kafka 的集成方式步骤详解

《Debezium与ApacheKafka的集成方式步骤详解》本文详细介绍了如何将Debezium与ApacheKafka集成,包括集成概述、步骤、注意事项等,通过KafkaConnect,D... 目录一、集成概述二、集成步骤1. 准备 Kafka 环境2. 配置 Kafka Connect3. 安装 D

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

Spring Cloud LoadBalancer 负载均衡详解

《SpringCloudLoadBalancer负载均衡详解》本文介绍了如何在SpringCloud中使用SpringCloudLoadBalancer实现客户端负载均衡,并详细讲解了轮询策略和... 目录1. 在 idea 上运行多个服务2. 问题引入3. 负载均衡4. Spring Cloud Load

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SQL 中多表查询的常见连接方式详解

《SQL中多表查询的常见连接方式详解》本文介绍SQL中多表查询的常见连接方式,包括内连接(INNERJOIN)、左连接(LEFTJOIN)、右连接(RIGHTJOIN)、全外连接(FULLOUTER... 目录一、连接类型图表(ASCII 形式)二、前置代码(创建示例表)三、连接方式代码示例1. 内连接(I

Go路由注册方法详解

《Go路由注册方法详解》Go语言中,http.NewServeMux()和http.HandleFunc()是两种不同的路由注册方式,前者创建独立的ServeMux实例,适合模块化和分层路由,灵活性高... 目录Go路由注册方法1. 路由注册的方式2. 路由器的独立性3. 灵活性4. 启动服务器的方式5.

Java中八大包装类举例详解(通俗易懂)

《Java中八大包装类举例详解(通俗易懂)》:本文主要介绍Java中的包装类,包括它们的作用、特点、用途以及如何进行装箱和拆箱,包装类还提供了许多实用方法,如转换、获取基本类型值、比较和类型检测,... 目录一、包装类(Wrapper Class)1、简要介绍2、包装类特点3、包装类用途二、装箱和拆箱1、装

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要