单元测试工具Pytest常用插件总结
发布于 2021-05-09 23:57 ,所属分类:软件测试工程师学习资料
出品|51Testing软件测试网
对于我们测试人来说,目前用到的最多的单元测试工具非pytest莫属。pytest本身已经给我们提供了很多功能了,但是如果结合它的第三方插件,那么pytest才是真正的属于我们测试编写自动化用例的强大工具。
今天安静就带大家来认识下pytest中的一些常用插件。
都说pytest比unittest好,那么具体好到哪些地方呢?这不就来了。
unittest和pytest目前本身框架中不支持用例失败重跑,但是pytest有强大的第三方插件: pytest-rerunfailures。
pytest-rerunfailures属于pytest的第三方插件,用来做测试用例失败后进行重新执行。
安装:
pip install pytest-rerunfailures
源码:
https://github.com/pytest-dev/pytest-rerunfailures
官方文档:
https://pypi.org/project/pytest-rerunfailures/
使用方法:
pytest-rerunfailures的使用方法有两种,安静拿实例具体演示。
方法一:装饰器
通过装饰器的方法来标记测试用例,当标记过的测试用例执行失败后,则重新进行执行。
@pytest.mark.flaky(reruns=3, reruns_delay=2)
# reruns =3:表示用例失败后需要重新执行几次,数字可以根据项目进行改变
# reruns_delay=2:表示用例失败后等待几秒再重新执行,数字可以根据项目进行改变
(左右滑动查看完整代码)
装饰器不仅仅在单独的用例中使用,还能在单独的测试类中进行执行。
装饰器在用例上:
这里安静通过随机值进行确定测试用例会存在失败,从而进行重新跑。
import pytest
import random
class Test01:
@pytest.mark.flaky(reruns=3, reruns_delay=2)
def test_01(self):
a = random.randint(0, 3)
print('---用例01---')
print(a)
assert a == 2
def test_02(self):
print('---用例02---')
assert 1 == 1
if __name__ == '__main__':
pytest.main(['-vs'])
(左右滑动查看完整代码)
通过下图可以看到,我们执行用例1一共执行了3次,第一次设置的随机值为1和断言2不一致,进行重新跑,第2次随机值为0和断言2也不一样,第3次的时候断言相同了,用例通过:
装饰器在类上:
import pytest
import random
@pytest.mark.flaky(reruns=3, reruns_delay=2)
class Test01:
def test_01(self):
a = random.randint(0, 2)
print('---用例01---')
print('用例01中的a:%s'%a)
assert a == 2
def test_02(self):
c = random.randint(0, 2)
print('---用例02---')
print('用例02中的c:%s'%c)
assert c == 1
if __name__ == '__main__':
pytest.main(['-vs'])
(左右滑动查看完整代码)
通过下方执行结果可以很清楚的看到,我们class下的用例都进行了失败重跑。
方法二:命令行
pytest-rerunfailures也可以通过命令行进行执行。
方式一:pytest --reruns 3 --reruns-delay 2
方式二:pytest -vs --reruns=3 --reruns-delay=2
# reruns:失败重新运行次数
# rerun-delay:表示失败后等待多少秒后重新执行
(左右滑动查看完整代码)
继续用上面的例子进行演示:
import pytest
import random
class Test01:
def test_01(self):
a = random.randint(0, 2)
print('---用例01---')
print('用例01中的a:%s'%a)
assert a == 2
def test_02(self):
c = random.randint(0, 2)
print('---用例02---')
print('用例02中的c:%s'%c)
assert c == 1
if __name__ == '__main__':
pytest.main(['-vs'])
(左右滑动查看完整代码)
打开cmd终端,进入到测试用例的目录中然后输入命令进行执行。
好了,失败重跑就这么多的知识,是不是很简单、很方便?这里安静提一句,装饰器的方法和命令行的方法不能同时使用,不然会报错的。
我们还是拿unittest和pytest来比较,unittest中的执行顺序是通过ASCll值排列方式来执行的,pytest是通过用例编写的先后顺序来执行的。
当在特点的场景下需要制定执行用例的顺序,如果按照以前的方法只能更改用例的名称来完成,但是pytest中的插件pytest-ordering来控制用例的执行顺序。
pytest-ordering属于pytest的第三方插件,用来控制pytest用例的执行顺序。
安装:
pip install pytest-ordering
源码:
https://github.com/ftobia/pytest-ordering
官方文档:
https://pypi.org/project/pytest-ordering/
使用方法:通过装饰器进行标记用例。
@pytest.mark.run(order=X)
# x:表示执行顺序
(左右滑动查看完整代码)
具体案例:
import pytest
class Test01():
@pytest.mark.run(order=3)
def test_02(self):
print('\n---用例02---')
@pytest.mark.run(order=2)
def test_01(self):
print('\n---用例01---')
@pytest.mark.run(order=1)
def test_03(self):
print('\n---用例03---')
if __name__ == '__main__':
pytest.main(['-vs'])
(左右滑动查看完整代码)
通过执行已经可以看出来按照我们的标记的顺序进行执行了。
这里大家也有注意的点,如果未标记的和标记的同时执行时,执行的顺序,先执行标记的,后按照编写顺序执行。
在我们执行测试用例时候,如果用例较多的话,可能会导致执行的速度过长。这时是否可以考虑下可不可以将用例并行进行测试?
其实方法是有的既然这里介绍的是pytest的插件,那么我们就通过pytest中的pytest-xdist的方法进行完成分布式执行。
pytest-xdist:表示在测试过程中可以使我们的测试用例一起并行测试,运行情况是根据你运行环境存在的CPU个数,运行过程中进行组合测试运行,从而加快我们的测试时间。
当我们在使用pytest-xdist时候,对编写的用例有一定的要求:
一定保证用例的独立性,用例之间互不影响;
一定保证用例的随机性,执行用例不能存在特定的顺序;
一定保证用例的重复性,每条用例的执行结果不影响到其他的用例。
安装:
pip install pytest-xdist
官方地址:
https://pypi.org/project/pytest-xdist/
使用方法:
pytest -n 2
# 其中后面的数字表示启动几个cpu来执行用例
pytest -n auto
# 其中auto表示启动当前系统的最大可用cpu数量
(左右滑动查看完整代码)
这里安静简单的举个例子给大家展示:
import pytest
import time
class TestCase:
def test_01(self):
time.sleep(2)
print('---测试用例01---')
def test_02(self):
time.sleep(2)
print('---测试用例02---')
def test_03(self):
time.sleep(2)
print('---测试用例03---')
def test_04(self):
time.sleep(2)
print('---测试用例04---')
assert 1 == 1
if __name__ == '__main__':
pytest.main(['-vs'])
(左右滑动查看完整代码)
上述代码中的time加了延迟是为了和后面进行分布式执行时方便对比执行时间。
这里发现执行结果用了8.07s的时间。那么当我们加上分布式并且加上2个cpu时,查看下执行速度,已经加快了3秒钟。
那么当我们调用电脑的最大cpu数量呢?这个执行速度已经达到了3.93秒。速度提高了很多。
在编写自动化测试用例的时候,可能一条用例存在这多条断言,那么在自动化中如何编写多条断言且断言失败后还能继续往下执行?这里引入新的插件pytest-assume。
pytest-assume:属于pytest的插件,可以在用例中使用多个断言,且断言时候后不影响其他的断言。
安装:
pip install pytest-assume
源码:
https://github.com/astraw38/pytest-assume
使用方法和普通的断言方式一样,唯一区别就是断言失败后,可以继续执行。
import pytest
class Test_01:
def test_01(self):
print('---用例01---')
pytest.assume('anjing' in 'test_anjing')
pytest.assume(1==2)
print('执行完成!')
def test_02(self):
print('---用例02---')
def test_03(self):
print('---用例03---')
if __name__ == '__main__':
pytest.main(['-vs'])
(左右滑动查看完整代码)
通过执行结果可以看出来,在第2个断言失败后,又继续执行下面的操作了。
编写测试用例之间讲究独立性,那么如果用例之间无法做到独立性,当第1个用例失败的时候与其存在依赖关系的用例也随之失败,那么这个时候有没有什么办法可以将当用例失败后,与其有依赖关系的用例将其不执行。
pytest中的插件pytest-dependency将完美的解决了这个问题。
pytest-dependency:属于pytest的插件,用来标记用例之间的依赖关系。
安装:
pip install pytest-dependency
源码:
https://github.com/RKrahl/pytest-dependency
使用方法:
import pytest
class TestCase:
@pytest.mark.dependency()
def test_01(self):
print('测试用例01')
assert 1 == 2
@pytest.mark.dependency(depends='test_01')
def test_02(self):
print('测试用例02依赖测试用例01')
@pytest.mark.dependency(name='test')
def test_03(self):
print('测试用例03')
assert 1==1
@pytest.mark.dependency(depends=['test'])
def test_04(self):
print('测试用例04依赖测试用例03')
if __name__ == '__main__':
pytest.main(['-vs'])
(左右滑动查看完整代码)
上述代码中提供了2种使用方法,一种之间通过装饰器@pytest.mark.dependency()的方法进行使用,另一种进行创建新的名字进行使用。
通过上述代码中也可以看到,用例2依赖于用例1,用例4依赖于用例3。通过执行,发现会有1个失败,2个成功和1个跳过。跳过的用例正是用例2,依赖的用例1失败了。
自动化测试完成后都会有一份详细的测试报告,作为目前最火的pytest单元测试框架,当然也有测试报告,测试报告是通过pytest的插件-pytest-html进行完成的。
pytest-html:属于pytest的第三方插件,用来生成测试报告。
安装:
pip install pytest-html
源码:
https://github.com/pytest-dev/pytest-html
使用方法:
直接在命令行参数中加入pytest--html=report.html其中report.html表示生成的报告文件名称。
import pytest
class TestCase:
def test_01(self):
print('\n测试用例01')
def test_02(self):
print('\n测试用例02')
@pytest.mark.skip()
def test_03(self):
print('\n测试用例03,跳过的测试用例')
def test_04(self):
print('\n测试用例04,失败的测试用例')
assert False
if __name__ == '__main__':
pytest.main(['-vs'])
(左右滑动查看完整代码)
可以从上图代码中看出,用例1和2是正常通过的,用例3是跳过的,用例4是失败的用例,分别通过这些用例查看在报告中的显示情况。
在命令行中输入pytest --html=report.html,然后会在当前目录中生成一个report.html的文件,打开后就是下图的内容。
出去面试的经常问到自动化测试用例的覆盖率是多少?达到100%了吗?这个问题对于我们的pytest来说也存在一个插件pytest-cov。
pytest-cov:属于pytest的第三方插件,常用来做单元测试的覆盖率。
安装:
pip install pytest-cov
源码:
https://github.com/pytest-dev/pytest-cov
使用方法:
这里安静只是列举出来如何使用,没有拿具体的实例进行测试。
class TestCase:
def test_01(self):
print('---测试用例01---')
def test_02(self):
print('---测试用例02---')
def test_03(self):
print('---测试用例03---')
def test_04(self):
print('---测试用例04---')
assert 1 == 1
(左右滑动查看完整代码)
在终端中通过输入命令pytest --cov进行覆盖率的结果,通过下图可以看出来,单元测试覆盖率只有10%,执行率是100%。
上述介绍了一些pytest常用的插件信息,那么当我们编写程序时候,需要一个个安装比较麻烦,这里安静介绍一个快捷安装需要库的方式。
在项目的根目录中创建requirements.txt的文件,将需要依赖的库全部都写入到文件中。
在根目录中通过终端打开,输入pip install -r requirements.txt这样的话就可以将我们所依赖的所有库都一起装入了。
安静简单的介绍了关于pytest的常用插件,这些插件对于我们执行自动化测试用例,以及编写测试用例都有非常好的作用。但是具体如何实践到公司的项目中,这个就要看大家如何使用了。
点击阅读☞接口自动化核心知识点浓缩,为面试加分!
点击阅读☞惊呆,原来QA需要具备这么多能力
点击阅读☞新人如何做好功能测试,看这几点就够了
点击阅读☞211本科大佬的真实面试经历:测试人要不要去外包公司?
点击阅读☞2020年应聘华为测试岗三轮面试经历分享
相关资源