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

相关文章

C#特性(Attributes)和反射(Reflection)详解

《C#特性(Attributes)和反射(Reflection)详解》:本文主要介绍C#特性(Attributes)和反射(Reflection),具有很好的参考价值,希望对大家有所帮助,如有错误... 目录特性特性的定义概念目的反射定义概念目的反射的主要功能包括使用反射的基本步骤特性和反射的关系总结特性

详解如何在SpringBoot控制器中处理用户数据

《详解如何在SpringBoot控制器中处理用户数据》在SpringBoot应用开发中,控制器(Controller)扮演着至关重要的角色,它负责接收用户请求、处理数据并返回响应,本文将深入浅出地讲解... 目录一、获取请求参数1.1 获取查询参数1.2 获取路径参数二、处理表单提交2.1 处理表单数据三、

PyQt6中QMainWindow组件的使用详解

《PyQt6中QMainWindow组件的使用详解》QMainWindow是PyQt6中用于构建桌面应用程序的基础组件,本文主要介绍了PyQt6中QMainWindow组件的使用,具有一定的参考价值,... 目录1. QMainWindow 组php件概述2. 使用 QMainWindow3. QMainW

MySQL中SQL的执行顺序详解

《MySQL中SQL的执行顺序详解》:本文主要介绍MySQL中SQL的执行顺序,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql中SQL的执行顺序SQL执行顺序MySQL的执行顺序SELECT语句定义SELECT语句执行顺序总结MySQL中SQL的执行顺序

Java资源管理和引用体系的使用详解

《Java资源管理和引用体系的使用详解》:本文主要介绍Java资源管理和引用体系的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Java的引用体系1、强引用 (Strong Reference)2、软引用 (Soft Reference)3、弱引用 (W

C语言中的常见进制转换详解(从二进制到十六进制)

《C语言中的常见进制转换详解(从二进制到十六进制)》进制转换是计算机编程中的一个常见任务,特别是在处理低级别的数据操作时,C语言作为一门底层编程语言,在进制转换方面提供了灵活的操作方式,今天,我们将深... 目录1、进制基础2、C语言中的进制转换2.1 从十进制转换为其他进制十进制转二进制十进制转八进制十进

MySQL中的两阶段提交详解(2PC)

《MySQL中的两阶段提交详解(2PC)》:本文主要介绍MySQL中的两阶段提交(2PC),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录引言两阶段提交过程sync_binlog配置innodb_flush_log_at_trx_commit配置总结引言在Inn

Python MCPInspector调试思路详解

《PythonMCPInspector调试思路详解》:本文主要介绍PythonMCPInspector调试思路详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋... 目录python-MCPInspector调试1-核心知识点2-思路整理1-核心思路2-核心代码3-参考网址

Java Jackson核心注解使用详解

《JavaJackson核心注解使用详解》:本文主要介绍JavaJackson核心注解的使用,​​Jackson核心注解​​用于控制Java对象与JSON之间的序列化、反序列化行为,简化字段映射... 目录前言一、@jsonProperty-指定JSON字段名二、@JsonIgnore-忽略字段三、@Jso

MySQL中隔离级别的使用详解

《MySQL中隔离级别的使用详解》:本文主要介绍MySQL中隔离级别的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录引言undo log的作用MVCC的实现有以下几个重要因素如何根据这些因素判断数据值?可重复读和已提交读区别?串行化隔离级别的实现幻读和可