pytest之@pytest.mark.pytest-dependency装饰器设置测试用例之间的依赖关系
前言
1、这是一个pytest第三方插件,主要解决用例之间的依赖关系。如果依赖的上下文测试用例失败后续的用例会被标识为跳过执行,相当于执行了 pytest.mark.skip
2、dependency可作用的范围有:session
、package
、module
、class
3、安装 pip install pytest-dependency
4、官方示例:pytest-denpendency
基本用法
在TestCase类下面编写的用例:
1、首先在用例开始的位置打上一个装饰器 @pytest.mark.dependency() ,这是代表这条用例作为主条件,如果这条用例失败,关联它的用例会跳过执行。
2、在被关联的用例上,也打上带参数的装饰器@pytest.mark.dependency(),depends
接受的参数是关联的依赖用例名。
3、在 depends 也可以用别名的方式指定用例名。
①Test类下函数路径实现方式【通过指定测试类下面的测试用例方法(相当于使用nodeid即测试用例路径的方式)】
运行结果:
②函数名依赖实现方式【通过指定需要依赖测试函数的测试方法名】
③通过别名指定方式【通过为指定的依赖设置依赖名name(即为被依赖的用例设置别名)】
定义依赖范围
官方API详解
我们可以看到scope可接受四种参数定义的类型('session','package','module'或'class')
scope='class'
- 作用于所属的类,外部类不会被关联。
运行结果:
scope='module'
- 不传递 scope参数即默认参数是 module ,作用于当前py文件。
- 只会查找当前文件的符合条件的文件名,类里同名的方法不会被依赖
运行结果:
scope='package'
- 作用于当前目录同级的依赖函数,跨目录无法找到依赖的函数。
运行结果:
scope='session'
- 作用域全局,可跨目录调用。但被依赖的用例必须先执行,如例子中的test01,否则用例会执行跳过!!!!
运行结果:
注意
①如果依赖的上下文测试用例使用 @pytest.mark.parametriz 进行用例参数化后,使用测试函数的方法名依赖方式无法实现测试用例的依赖。【因为通过 .pytest_cache 文件我们知道测试用例的nodeid为 路径+用例参数化的参数 ,当依赖的上下文测试用例中使用用例参数化时,用例的nodeid已经不在单纯的只是具体到测试方法,而是具体到改用例的参数】
②我们在使用测试方法依赖的时候,可以在依赖参数化用例的同时,将被依赖测试方法的完整的nodid传到依赖测试方法的depnds入参中,如下正常①。
③或者为依赖和被依赖的测试方法使用指定别名的方式进行上下文用例的依赖,如下正常②。
④用例之间的依赖情况一般出现于类似业务主流程的测试脚本中(即一个模块里面可能有多个测试方法,并且测试方法之间具有业务关联关系),所以一般来说用例的参数化中只有一个用例(即该测试方法虽然进行了用例参数化,但还是相当于只是一条用例:例如产生一条具体的测试数据)。
⑤当然,如果被依赖的测试方法中用例参数化后形成了多条测试用例,那么就有多条测试用例被依赖,且被依赖的测试用例的执行结果全部为PASSED时,依赖的测试方法才会执行,否则依赖的测试方法仍然会被跳过。
例如:
非正常:
test_d测试用例依赖test_a测试用例,test_b测试用例依赖test_d测试用例,test_c测试用例依赖test_b测试用例。
import pytest from tools.common.log_process import * @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency() @pytest.mark.parametrize('data', [1]) def test_a(data): # data = 1 assert data == 1 @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency(depends=['test_a']) def test_d(): assert True @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency(depends=['test_d']) def test_b(): assert 'ooo' == 'oo' @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency(depends=['test_b']) def test_c(): assert 'lll' is 'lll'
运行结果:
正常①:
# -*- encoding:utf-8 -*- import pytest from tools.common.log_process import * @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency() @pytest.mark.parametrize('data', [1]) def test_a(data): # data = 1 assert data == 1 @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency(depends=['test_a[1]']) def test_d(): assert True @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency(depends=['test_d']) def test_b(): assert 'ooo' == 'oo' @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency(depends=['test_b']) def test_c(): assert 'lll' is 'lll'
运行结果:
正常②
# -*- encoding:utf-8 -*- import pytest from tools.common.log_process import * @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency(name='a') @pytest.mark.parametrize('data', [1]) def test_a(data): # data = 1 assert data == 1 @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency(name='b', depends=['a']) def test_d(): assert True @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency(name='c', depends=['b']) def test_b(): assert 'ooo' == 'oo' @record(os.path.basename(__file__).split('.')[0]) @pytest.mark.dependency(depends=['c']) def test_c(): assert 'lll' is 'lll'
运行结果: