场景
使用pytest-xdist实现测试用例的并发执行, 但是执行中部分用例需要设置执行顺序
需要的依赖包
pytest-order , pytest-xdist, pytest-dependency
实现方法
-
对执行顺序有要求的用例设置, 设置在同一个组中并且设置执行顺序,用例上设置@pytest.mark.xdist_group(name="group_name"), 并且执行时设置参数 -dist loadgroup , 就能保证group名字相同的用例在同一个worker中运行
-
然后对同一个group中的用例设置顺序,即@pytest.mark.order(1)
-
如果用例间有依赖的话,可以对被依赖和依赖的用例设置依赖关系
python@pytest.mark.dependency(name="test_name") @pytest.mark.dependency(depends=["test_name"])
验证
-
有一个文件test_1.py, 内容如下
pythondef test_one(): pass def test_two(): pass
执行
pytest test_1.py -v -n 2
输出结果: test_one和test_two分别属于gw0 和gw1
shelltest_case/test_1.py::test_one test_case/test_1.py::test_two [gw0] [ 50%] PASSED test_case/test_1.py::test_one [gw1] [100%] PASSED test_case/test_1.py::test_two
-
添加group后test_1.py文件内容
python@pytest.mark.xdist_group(name="group_name") def test_one(): pass @pytest.mark.xdist_group(name="group_name") def test_two(): pass
执行
pytest test_1.py -v --dist loadgroup -n 2
输出结果:test_one和test_two属于同一个worker gw0
shelltest_case/test_1.py::test_one@group_name [gw0] [ 50%] PASSED test_case/test_1.py::test_one@group_name test_case/test_1.py::test_two@group_name [gw0] [100%] PASSED test_case/test_1.py::test_two@group_name
-
添加执行顺序后test_1.py文件内容
python@pytest.mark.xdist_group(name="group_name") @pytest.mark.order(2) def test_one(): pass @pytest.mark.xdist_group(name="group_name") @pytest.mark.order(1) def test_two(): pass
执行
pytest test_1.py -v --dist loadgroup -n 2
输出结果: 用例在gw0中并且按顺序执行
shelltest_case/test_1.py::test_two@group_name [gw0] [ 50%] PASSED test_case/test_1.py::test_two@group_name test_case/test_1.py::test_one@group_name [gw0] [100%] PASSED test_case/test_1.py::test_one@group_name
-
新建文件test_2.py文件内容
pythonimport pytest @pytest.mark.dependency(depends=["test_name"]) def test_three(): pass
修改test_1.py文件内容
pythonimport pytest @pytest.mark.dependency(name="test name") @pytest.mark.xdist_group(name="group_name") @pytest.mark.order(2) def test_one(): pass @pytest.mark.xdist_group(name="group_name") @pytest.mark.order(1) def test_two(): pass
执行结果如下, test_three是skipped状态
shelltest_case/test_1.py::test_two@group_name test_case/test_2.py::test_three [gw1] [ 33%] SKIPPED test_case/test_2.py::test_three [gw0] [ 66%] PASSED test_case/test_1.py::test_two@group_name test_case/test_1.py::test_one@group_name [gw0] [100%] PASSED test_case/test_1.py::test_one@group_name
修改一下test_2.py
pythonimport pytest @pytest.mark.xdist_group(name="group_name") @pytest.mark.dependency(depends=["test name"],scope='session') @pytest.mark.order(3) def test_three(): pass
再次执行结果, 按指定顺序执行
shelltest_case/test_1.py::test_two@group_name [gw0] [ 33%] PASSED test_case/test_1.py::test_two@group_name test_case/test_1.py::test_one@group_name [gw0] [ 66%] PASSED test_case/test_1.py::test_one@group_name test_case/test_2.py::test_three@group_name [gw0] [100%] PASSED test_case/test_2.py::test_three@group_name
经验之谈: 对于dependency不建议多用,用例设计的时候就需要考虑用例之间解耦,特别是对于UI自动化,为了保证通过率,需要设置失败重新运行,如果设置的依赖,很有可能出现被依赖的用例执行成功,但是依赖的用例是skipped状态