单元测试工具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 pytestimport randomclass 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 == 1if __name__ == '__main__':    pytest.main(['-vs'])

(左右滑动查看完整代码)


通过下图可以看到,我们执行用例1一共执行了3次,第一次设置的随机值为1和断言2不一致,进行重新跑,第2次随机值为0和断言2也不一样,第3次的时候断言相同了,用例通过:


装饰器在类上:

import pytestimport 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 == 1if __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 pytestimport randomclass 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 == 1if __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 pytestclass 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 pytestimport timeclass 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 == 1if __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 pytestclass 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 pytestclass 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 pytestclass 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的常用插件,这些插件对于我们执行自动化测试用例,以及编写测试用例都有非常好的作用。但是具体如何实践到公司的项目中,这个就要看大家如何使用了。



......
本文为51Testing软件测试网
第六十一期电子杂志内容
剩余精彩内容请点击下方查看

推荐阅读

点击阅读☞接口自动化核心知识点浓缩,为面试加分!

点击阅读☞惊呆,原来QA需要具备这么多能力

点击阅读☞新人如何做好功能测试,看这几点就够了

点击阅读☞211本科大佬的真实面试经历:测试人要不要去外包公司?

点击阅读☞2020年应聘华为测试岗三轮面试经历分享

“”一起来充电吧!

相关资源