pytest
Posted fengye151
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pytest相关的知识,希望对你有一定的参考价值。
pytest作为第三方自动化测试框架,深受大家的喜爱。本文主要介绍pytest框架进行自动化测试的API函数基础、经验和技巧。
API函数基础
我们先来“禅”一下,看看python的设计哲学
Beautiful is better than ugly.
优美胜于丑陋
Explicit is better than implicit.
明了胜于晦涩
Simple is better than complex.
简单胜过复杂
Complex is better than complicated.
复杂胜过凌乱
Flat is better than nested.
扁平胜于嵌套
Sparse is better than dense.
间隔胜于紧凑
Readability counts.
可读性很重要
Special cases aren‘t special enough to break the rules.
即使假借特例的实用性之名,也不违背这些规则
Although practicality beats purity.
虽然实用性次于纯度
Errors should never pass silently.
错误不应该被无声的忽略
Unless explicitly silenced.
除非明确的沉默
In the face of ambiguity, refuse the temptation to guess.
当存在多种可能时,不要尝试去猜测
There should be one-- and preferably only one --obvious way to do it.
应该有一个,最好只有一个,明显能做到这一点
Although that way may not be obvious at first unless you‘re Dutch.
虽然这种方式可能不容易,除非你是python之父
Now is better than never.
现在做总比不做好
Although never is often better than *right* now.
虽然过去从未比现在好
If the implementation is hard to explain, it‘s a bad idea.
如果这个实现不容易解释,那么它肯定是坏主意
If the implementation is easy to explain, it may be a good idea.
如果这个实现容易解释,那么它很可能是个好主意
Namespaces are one honking great idea -- let‘s do more of those!
命名空间是一种绝妙的理念,应当多加利用
以上就是 Python 之禅,python之父把一番人生哲学嵌在python解释器中啊。
为什么要提起这个?下面介绍的强制等待的完美应用道理就在其中。
(1) 显式等待&隐式等待&强制等待
了解一下python三种等待机制:
time.sleep
强制等待,设置固定休眠时间,线程休眠,而另外两种等待线程不休眠;
driver.implicitly_wait
隐式等待,是设置的全局等待。设置等待时间后,对页面中所有元素设置加载时间,即整个页面的加载时间,如果超出了设置的时间还未找到元素则会抛出异常。可以理解为在规定的时间范围内,浏览器在不停地刷新页面,直到找到相应元素或者时间结束;
WebDriverWait()
显式等待,是针对某个特定元素设置等待时间。在设置时间内,默认每隔一段时间检测一次当前页面某个元素是否存在,如果在规定的时间内找到该元素则直接执行,即找到相关元素就执行相关操作,如果超出检测时间则抛出异常。默认检测频率为0.5s,默认抛出异常为NoSuchElementException。
举个例子说说它们的对比应用。有一组Textview,要实现某一项的选择,比如第一个选项,然后点击确定按钮的操作。
如果用driver.implicitly_wait隐式等待,执行结果会是这样:需要选择的第一项不会被选;
换成time.sleep强制等待后,可以实现第一项“在用”的选择。
再举例,我们经常会遇到确认弹窗,当存在这种dialog时最好也用强制等待,很简单,很实用。
代码如下
ele2 = appdriver.find_element_by_xpath("//android.widget.TextView[contains(@text,‘12345678‘)]")
TouchAction(appdriver).long_press(ele2).perform()
appdriver.find_element_by_id(‘android:id/button1‘).click()
time.sleep(3)
删除确认弹窗,要用time.sleep(),避免dialog未加载结束而定位不到元素。
(2)全局变量
对于多个函数都会使用到的变量,可以在函数以外进行统一定义。在函数内,如果使用其他变量的值,可以在函数内继续赋值,不影响使用。
patno=‘No‘
def test_ add(appdriver):
appdriver.find_element_by_id(‘number‘).send_keys(patno)
appdriver.find_element_by_android_uiautomator(‘text("确定")‘).click()
assert ‘信息‘ in title
appdriver.find_element_by_id(‘delete_btn‘).click()
appdriver.find_element_by_id(‘android:id/button1‘).click()
appdriver.implicitly_wait(3)
def test_ edit(appdriver):
appdriver.find_element_by_id(‘number‘).send_keys(patno)
appdriver.find_element_by_android_uiautomator(‘text("确定")‘).click()
assert ‘ No‘ in number
appdriver.implicitly_wait(3)
是不是很简洁?
(3)Float与string类型转换
先来了解round() 方法,它返回浮点数x的四舍五入值。
round() 方法的语法:round( x [, n] )
参数说明:
x -- 数值表达式。
n -- 数值表达式。
返回值:
返回浮点数x的四舍五入值。
如果需要实现四舍五入取小数点后2位,格式为round(a,2),
例如a=1.987 round(a,2)=1.99
value = 200
value1=appdriver.find_element_by_id(‘tv_dang‘).text
assert str(round(value/0.02,2)) == value1
上面对进行运算的值,赋值时为数值类型,如value = 200,
运算之后进行断言,左边round(value/0.02,2)是浮点型,需要转换为string,右边value1是string类型,这样可以实现断言类型的匹配。
因为string进行比较时,两者必须完全一致,断言才能相等。
如果遇到round函数得到的小数尾部含0时,例如2.00,会显示成2.0,这时候断言会报错。
这里再进一步优化,把右边value1强制转换成float类型,与左边的进行比较,小数点最后的0个数不会影响到数值之间的比较,这样就能保证不管左右两边的数值多么特殊,都可以使得断言正确。
(3) 当前页面弹出新窗口时 想要定位弹窗元素
需要重新获取一下页面元素,以避免报错:selenium.common.exceptions.StaleElementReferenceException: Message: io.appium.uiautomator2.common.exceptions.StaleElementReferenceException: The element ‘By.id: title‘ does not exist in DOM anymore
具体实现代码:
try:
appdriver.find_element_by_id(‘title‘)
except Exception as e:
appdriver.find_element_by_id(‘title‘)
assert appdriver.find_element_by_id(‘title‘).text =="不在线"
appdriver.find_element_by_id(‘negativeTextView‘).click()
类似,在返回两次页面情况下,最好加上重新查找元素的保护,免得程序报错。
(4)driver.close()和driver.quit()的不同点
driver.quit()与driver.close()的不同:
driver.quit(): Quit this driver, closing every associated windows;退出driver,关闭每个相关的窗口
driver.close(): Close the current window, quiting the browser if it is the last window currently open.关闭当前窗口,如果它是最近打开的窗口则退出浏览器
在pytest的conftest中定义登录退出login/logout函数,在logout中不可以添加driver.close(),因为添加之后,执行完成一个python文件,driver被关闭,而无法继续执行下一个python文件。
def logout(appdriver):
print("Testing ends.")
appdriver.find_element_by_id(‘center‘).click()
appdriver.implicitly_wait(2)
appdriver.find_element_by_android_uiautomator(‘text("设置")‘).click()
appdriver.find_element_by_id(‘exit_btn‘).click()
appdriver.find_element_by_id(‘android:id/button1‘).click()
appdriver.implicitly_wait(3)
pytest调试的技巧
pytest默认正确运行后,不会输出print调试语句,但是有些调试语句是必须的,帮助我们了解返回的数据是否正常。这里提供两种解决方案:
方案一 结合pytest和unittest框架,即在测试用例目录下既使用pytest、又使用unittest。对于我们需要输出的print信息采用unittest。具体实现的文件结构目录如下
--TestCase
--testreport
--conftest.py
--test1.py
--test2.py
test1.py采用pytest,而test2.py的文件采用unittest。
这样在项目中灵活组合,不仅可以一起运行成功,而且融合了pytest和unittest各自的优势,需要展示调试信息的给予展示。
方案二 pytest文件输出结果加上参数 –s
if __name__ ==‘__main__‘:
now = time.strftime("%Y%m%d_%H%M",time.localtime(time.time()))
reportfile = ‘./testreport/‘ + now + ‘result.html‘
pytest.main(["-s"])
在Pycharm中可以看到print调试信息
注意:集成到jenkins时,配置文件里最好也加上参数,保证print信息的输出。
例如jenkins配置填写
pytest -s test_addnew.py
Jenkins运行build结果展示如下:
控制台输出
Started by user admin
Running as SYSTEM
Building in workspace C:Usersadmin.jenkinsworkspace新增
[新增] $ cmd /c call e:dev omcat empjenkins3471635495886325015.bat
C:Usersadmin.jenkinsworkspace新增>e:
E:>cd E:ats est_web
E:ats est_web >pytest -s test_add.py
============================= test session starts =============================
platform win32 -- Python 3.7.0, pytest-5.3.2, py-1.7.0, pluggy-0.13.1
rootdir: E:ats est_web
plugins: html-1.20.0, metadata-1.8.0, rerunfailures-8.0
collected 3 items
test_add.py web login...
识别码为 6605
新密码为: 123456
该测试用例执行通过
.web logout.
.
============================= 3 passed in 24.72s ==============================
E:ats est_web >exit 0
Finished: SUCCESS
以上是关于pytest的主要内容,如果未能解决你的问题,请参考以下文章