本栏目内的所有项目使用的都是PyCharm 2020.1专业版,可以下载后自行在网上找教程破解。
WEB UI自动化测试框架搭建(一)~(七)源代码:https://download.csdn.net/download/qq_38175040/18339296
前言
我们以如下一段代码为例,刚刚初学完selenium的人差不多都是这样写的吧:
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://mail.163.com/')
i_frame = driver.find_element_by_tag_name('iframe')
driver.switch_to.frame(i_frame)
driver.find_element_by_name('email').send_keys('my_username')
driver.find_element_by_name('password').send_keys('my_password')
driver.find_element_by_id('dologin').click()
上述代码这只是简单尝试了登录网易邮箱。这段代码非常线性,把需要的操作一行一行的以代码的形式写了下来。
首先,设想一下,如果我们需要测试一个完整的系统,以这种方式编写代码可能得写个1000~2000行。这么长的代码很难读,而且一旦系统页面的元素发生变更,在上千行的代码中准确找到需要修改的地方足以让人崩溃。
其次,这样的代码还有一个致命的缺点,就是只能测试一个系统。如果要测试其他系统,就只能把一堆的find_element
和 send_keys
逐个修改并且代码需要极大幅度的改动,这显然不可能。
我们用搭建自动化测试框架来拒绝上面这种线性并且要命的代码。
PO模式
提到WEB UI自动化框架就不得不提到PO模式。在实际的测试过程中,由于每个公司的页面变化的频率基本都很频繁,相应地自动化也要变更,加大了难度。于是有人提出了PO模式,其中最基本的概念就是每个页面都被视为一个类,如果实际操作过程中页面的元素被修改,那么我们随之修改页面对应的类即可,可维护性大大提高。
我们的WEB UI自动化框架核心由以下三个模块构成:
对象层: 用于存放各页面,每个页面被看作一个类。(类中具体实现了元素的定位和控件的操作)
逻辑层: 一些功能用例的模块 (如登录,退出登录,修改密码分属不同的模块)
业务层: 真正实现测试用例的操作部分(将对不同模块的操作组合起来,最终实现对一个完整系统的自动化测试)
Utils包,其下存放所有的公共方法及工具类
在前言的那一坨代码里,不管行数多少,显而易见的出现次数最多的就是find_element
了,因为自动化操作过程中做的最多的就是定位各个元素并进行操作。
同时,如果在操作过程中我们将等待延迟等因素考虑在内,我们通常还会在代码里加上很多的time.sleep()
。代码里全部都是find_element
和time.sleep()
,行数一多简直辣眼睛。
因而,我们引入了Utils模块,将所有公用的方法封装在其中。
1.我们首先新建一个工程:
2.并在该工程下创建一个.py文件,其中的内容就是前言里粘贴的那一段代码。
可以看到有三个find_element,我们接下来将其封装为公用方法。
3.在该工程下新建一个package
并将该package命名为Utils,在该包内存放所有的公共方法。
4.在Utils包下面新建一个fin_ele.py
文件,这个文件会封装所有的driver.find_element_
方法
接下来我们来详细写一下find_element
函数以封装所有其他文件用到的driver.find_element_
方法。
传三个参数进去:driver,根据name或者id查找的find_type以及具体的值,这样定位元素的封装函数就定义完成。
然后来写一下这个函数。
def find_element(driver,find_type,find_key):
element = driver.find_element(by=find_type,value=find_key)
return element
这样就简单封装好了啊。
5.然后改写login_test.py内的driver.find_element_
方法。
贴一下代码:
from selenium import webdriver
from Utils.fin_ele import find_element
driver = webdriver.Chrome()
driver.get('https://mail.163.com/')
i_frame = driver.find_element_by_tag_name('iframe')
driver.switch_to.frame(i_frame)
# driver.find_element_by_name('email').send_keys('my_username')
# driver.find_element_by_name('password').send_keys('my_password')
# driver.find_element_by_id('dologin').click()
find_element(driver,'name','email').send_keys('my_username')
find_element(driver,'name','password').send_keys('my_password')
find_element(driver,'id','dologin').click()
find_element这个函数没有声明,需要导入一下。
然后运行此时的login_test.py,发现效果和之前一样。
6.在代码中添加time.sleep()然后优化封装
重写一下封装方法:
from selenium.webdriver.support.wait import WebDriverWait
def find_element(driver,find_type,find_key):
# element = driver.find_element(by=find_type,value=find_key)
# return element
try:
element = WebDriverWait(driver,10).until(lambda driver:driver.find_element(by = find_type,value = find_key))
return element
except Exception as e:
raise e
使用WebDriverWait比在代码中硬塞很多time.sleep()高级很多,time.sleep()是每次都必定等待这么长的时间。而WebDriverWait可以在规定的时间内等待后续的查找元素或者输入内容等操作的返回结果,若操作成功则跳过这次规定等待的剩余时间继续执行下一步操作,而如果在这次规定的时间内仍然没有操作成功,就会报错。
然后将login_test.py文件中的time.sleep()全部去掉。
import time
from selenium import webdriver
from Utils.fin_ele import find_element
driver = webdriver.Chrome()
driver.get('https://mail.163.com/')
i_frame = driver.find_element_by_tag_name('iframe')
driver.switch_to.frame(i_frame)
# driver.find_element_by_name('email').send_keys('my_username')
# driver.find_element_by_name('password').send_keys('my_password')
# driver.find_element_by_id('dologin').click()
find_element(driver,'name','email').send_keys('my_username')
find_element(driver,'name','password').send_keys('my_password')
find_element(driver,'id','dologin').click()
去掉time.sleep()之后运行程序,这三步的find_element
每一步都操作成功,跳过了WebDriverWait规定的等待时间,在一秒内执行完成,如果继续使用time.sleep()的话这边可能要执行6~7秒。