乐趣区

关于pytest:Pytest常用插件

本文首发于:行者 AI

Pytest 是 Python 的一种单元测试框架,与 unittest 相比,应用起来更简洁、效率更高,也是目前大部分应用 python 编写测试用例的小伙伴们的第一抉择了。

除了框架自身提供的性能外,Pytest 还反对上百种第三方插件,良好的扩展性能够更好的满足大家在用例设计时的不同需要。本文将为大家具体介绍上面 5 项罕用的插件。

1. 用例依赖

编写用例的时候,咱们会留神用例之间的独立性,但局部用例之间的确存在关联,无奈做到彻底独立,那么咱们就能够通过应用插件 pytest-dependency 设置用例之间的依赖关系。当用例 A 依赖于用例 B 时,若用例 B 执行失败,则用例 A 将会主动跳过不执行。如此,就能够防止去执行一个必定会失败的用例,相当于 pytest.mark.skip。

(1)装置:

pip install pytest-dependency

(2)应用阐明:

首先,在标记被依赖用例时,须要在被依赖的用例上增加装璜器 pytest.mark.dependency(),且被依赖用例须要在关联用例前执行。也能够给被依赖用例设置别名,通过增加参数 name 实现。

在关联的依赖用例上,同样须要增加装璜器 pytest.mark.dependency(depends=[‘ 用例名称 ’]),与之前不同的是,装璜器必须要填写 depends 参数实现用例的关联,关联的被依赖用例存在多个时能够应用“,”隔开。

此外,还能够通过 scope 参数指定用例依赖的范畴,同样是 session、package、module、class 这四种类型,此处不具体开展。

具体通过下方的示例以及执行后果来进一步阐明。

(3)示例及执行后果剖析

示例:

import pytest


class TestCase:

    # 通过装璜器 @pytest.mark.dependency()标记以后用例为被依赖用例,被依赖用例须要优先关联用例执行
    @pytest.mark.dependency()
    def test_01(self):
        print("测试用例 01,执行失败")
        assert 1 == 2

    # 通过应用装璜器关联被依赖用例,通过 depends 参数指定用例名称关联用例
    @pytest.mark.dependency(depends=['test_01'])
    def test_02(self):
        print("测试用例 02,跳过")

    # 标记被依赖用例时,能够通过 name 参数指定别名
    @pytest.mark.dependency(name="func_2")
    def test_03(self):
        print("测试用例 03,执行胜利!")

    # 应用 depends 参数指定定义的别名关联用例
    @pytest.mark.dependency(depends=['func_2'])
    def test_04(self):
        print("测试用例 04,执行胜利!")

    # depends 参数能够关联多个测试用例,应用“,”分隔即可
    @pytest.mark.dependency(depends=['test_01', 'func_2'])
    def test_05(self):
        print("测试用例 05,跳过")


if __name__ == '__main__':
    pytest.main(['-vs'])

执行后果如下:

咱们能够看出,只有依赖用例执行胜利时,以后用例才会被执行,否则会被跳过。依赖多个用例时,只有全副胜利,才会执行,否则一样会跳过。

2. 失败重跑

有些状况下,用例在执行过程中可能会受到一些客观因素的影响,导致用例执行失败,通过应用 pytest-rerunfailures 插件,能够在失败后从新执行用例,并设置从新运行的最大次数。以此保障用例执行后果的准确性。

(1)装置:

pip install pytest-rerunfailures

(2)应用阐明:

失败重跑共有两种应用形式,别离是通过装璜器执行和命令行执行。

应用装璜器时,须要在用例上增加装璜器 pytest.mark.flaky(reruns= 从新执行最大次数, reruns_delay= 执行间隔时间(单位:秒)),在执行过程中,增加了装璜器的用例在执行失败后会依照设置的次数和工夫从新执行。

通过在命令行执行时,同样须要指定 ”rerun” 和 ”rerun-delay” 两个参数来实现,如:pytest –reruns 从新执行最大次数 –reruns-delay 间隔时间。

留神:reruns 是从新执行的最大次数,如果在达到这一数量前用例执行胜利,则不会持续重跑,判断用例执行通过;否则执行到最大次数后,用例仍失败,则判断用例执行失败。

具体通过下方的示例和执行后果进一步阐明。

(3)示例及执行后果剖析

示例:

import pytest
import random


class TestCase:
    
    # 应用装璜器设置用例失败后的从新执行最大次数和每次执行的间隔时间(单位:秒)@pytest.mark.flaky(reruns=3, reruns_delay=1)
    def test_01(self):
        result = random.choice(['a', 'b', 'c', 'd', 'e'])
        print(f"result={result}")
        assert result == 'c'


if __name__ == '__main__':
    pytest.main(['-vs'])

执行后果如下:

咱们能够看出,当用例断言失败后,会从新执行,直到达到设置的最大次数或执行胜利为止。

3. 指定用例执行程序

pytest 在执行用例的时候,默认是依照文件中用例的先后顺序执行,有时咱们可能在保护测试用例时遇到须要批改用例执行程序的状况,然而如果每次都通过批改大段的用例代码先后地位来管制,并不利于保护。因而,应用插件 pytest-ordering 能够疾速实现用例执行程序的设置,前期保护时,也只须要批改对应的执行程序参数即可。

(1)装置:

pip install pytest-ordering

(2)应用阐明:

通过给用例增加装璜器 pytest.mark.run(order= 执行程序)设置用例的执行程序。在执行的时候,应用装璜器 pytest.mark.run 的用例会优先没有装璜器的用例执行,设置了执行程序的用例则依照 order 参数设置的大小升序执行。

具体通过下方的示例和执行后果进一步阐明。

(3)示例及执行后果剖析

示例:

import pytest


class TestCase:

    def test_01(self):
        print("测试用例 01")

    def test_02(self):
        print("测试用例 02")
    
    # 应用装璜器设置执行程序为 2
    @pytest.mark.run(order=2)
    def test_03(self):
        print("测试用例 03")
    
    # 应用装璜器设置执行程序为 1
    @pytest.mark.run(order=1)
    def test_04(self):
        print("测试用例 04")


if __name__ == "__main__":
    pytest.main(['-vs'])

执行后果:

咱们能够看出,执行的程序和预期统一。优先执行表明了执行程序的用例,并依照 order 的值由小到大执行。

4. 分布式运行

当我的项目的用例很多的时候,执行通常会耗时颇久,通过分布式运行,则能够大量缩短整体用例的执行工夫。pytest-xdist 插件就能够帮忙咱们实现测试用例的分布式运行。

(1)装置:

pip install pytest-xdist

(2)应用阐明:

在命令行执行用例时,通过参数 - n 设置并行启动的过程数量。除了设置具体的数量外,还能够设置为 auto,这种状况下,会根据以后设施的 cpu 数量执行。

此外,还能够通过 –dist 参数,设置用例分组,同一个组内的用例会在同一个过程中执行。

  • –dist=loadscope 同一个 module 或同一个 class 下的用例会调配为同一组,按 class 分组优先于 module。
  • –dist=loadfile 同一个.py 文件中的用例会调配为同一组。

具体通过下方的示例和执行后果进一步阐明。

(3)示例及执行后果剖析

示例:

import pytest
from time import sleep


class TestCase1:

    @pytest.mark.parametrize('keyword', ['a', 'b', 'c', 'd', 'e',
                                         'f', 'g', 'h', 'i', 'j'])
    def test_baidu_search(self, keyword):
        sleep(1)
        print(f'搜寻关键字{keyword}')


class TestCase2:

    @pytest.mark.parametrize('user', ['user1', 'user2', 'user3', 'user4', 'user5',
                                      'user6', 'user7', 'user8', 'user9', 'user10'])    def test_login(self, user):
        sleep(1)
        print(f'用户 {user} 登录胜利')


if __name__ == '__main__':
    # pytest.main(['-vs']) # 不应用 pytest-xdist 运行
    pytest.main(['-vs', '-n', '2']) # 应用 pytest-xdist 运行

执行后果:

从上方的两次执行后果中能够看出,应用分布式运行后,用例的运行工夫显著缩短。示例中的用例彼此之间没有关联,如果理论应用时用例之间存在依赖关系,能够应用 –dist 参数为用例分组,确保关联的用例在同一组内。

5. 多重断言

有时,在一个用例中,咱们须要对后果进行不同维度的多个断言,然而应用 assert 断言时,只有有一个断言失败,后续的断言就不会继续执行。当初,咱们能够通过应用 pytest-assume 插件来解决这个问题,当断言失败后,仍会继续执行后续的断言。

(1)装置:

pip install pytest-assume

(2)应用阐明:

在用例中,把应用 assert 进行的断言,改为应用 pytest.assume()进行断言即可。

具体通过下方的示例和执行后果进一步阐明。

(3)示例及执行后果剖析

示例:

import pytest


class TestCase:
    
    # 应用 assert 断言
    def test_01(self):
        print("断言 1")
        assert 1 == 1
        print('断言 2')
        assert 2 == 1
        print("断言 3")
        assert 3 == 3
        print('用例完结')
    
    # 应用 pytest.assume()断言
    def test_02(self):
        print('断言 1')
        pytest.assume(1 == 1)
        print('断言 2')
        pytest.assume(2 == 1)
        print('断言 3')
        pytest.assume(3 == 3)
        print('用例完结')


if __name__ == '__main__':
    pytest.main(['-vs'])

执行后果:

从执行后果中能够看出,应用 assert 断言时,断言失败不会再执行后续的内容;而应用 pytest.assume()断言时,断言失败仍会执行至用例完结。这样更有利于咱们一次性获取用例执行中全副错误信息。

6. 小结

本文为大家介绍了一些罕用的 pytest 框架的插件,能够帮忙咱们解决一些理论应用过程中遇到的问题。目前,pytest 反对的插件曾经多达 868 个,除了本文介绍的 5 个罕用插件外,还有很多反对其它需要的插件,大家能够依据本人的须要尝试查找应用相干的插件,以便可能更好的设计出合乎业务场景的测试用例。

退出移动版