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函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

MySQL中的锁机制详解之全局锁,表级锁,行级锁

《MySQL中的锁机制详解之全局锁,表级锁,行级锁》MySQL锁机制通过全局、表级、行级锁控制并发,保障数据一致性与隔离性,全局锁适用于全库备份,表级锁适合读多写少场景,行级锁(InnoDB)实现高并... 目录一、锁机制基础:从并发问题到锁分类1.1 并发访问的三大问题1.2 锁的核心作用1.3 锁粒度分

MySQL数据库中ENUM的用法是什么详解

《MySQL数据库中ENUM的用法是什么详解》ENUM是一个字符串对象,用于指定一组预定义的值,并可在创建表时使用,下面:本文主要介绍MySQL数据库中ENUM的用法是什么的相关资料,文中通过代码... 目录mysql 中 ENUM 的用法一、ENUM 的定义与语法二、ENUM 的特点三、ENUM 的用法1

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

一文详解Git中分支本地和远程删除的方法

《一文详解Git中分支本地和远程删除的方法》在使用Git进行版本控制的过程中,我们会创建多个分支来进行不同功能的开发,这就容易涉及到如何正确地删除本地分支和远程分支,下面我们就来看看相关的实现方法吧... 目录技术背景实现步骤删除本地分支删除远程www.chinasem.cn分支同步删除信息到其他机器示例步骤

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁