背景

在用 pytes 做自动化测试的时候,有时候我们的用例会非常多,特别是在用例参数化的时候。很容易就会有上千条的用例。可能每个用例又会有 IO 等待。如果顺序运行的话,就会很耗时。所以希望可以并发运行用例。这时可以用 pytest-xdist。这个网上有很多教程,这里不说了。主要说一下 pytest-xdist 的缺点

pytest-xdist 的缺点

为了解决上述问题。我为 pytest 写了这个插件。我把它叫做 pytest-multithreading。有以下好处

pytest-multithreading 的基本使用方法

先安装 pytest-multithreading。直接输入 pip install pytest-multithreading 安装

运行时用--th 参数指定最大创建的线程数,就可以并发运行测试用例了。
以下是使用示例

import time

import pytest


test_data_list = [i for i in range(1,1000)]
@pytest.mark.parametrize("i",test_data_list)
def test_multithreading(i):
    time.sleep(2)
    assert 1 == 1


if __name__ ==  "__main__":
   #--th是指定最大线程数,即最大并发运行的用例。这1000个用例会并发运行
    pytest.main(["test_pytest.py","-x","--th=1000"])


pytest-multithreading 插件可以标记特定的测试用例不并发运行

我们知道如果想要并发运行测试用例。就要让所有的用例都没有依赖关系,每个用例不能干扰其它用例的运行。但是有些用例要 reload 程序,这会干扰其它用例的运行。所以要让这些用例独立运行,不能让其参与并发运行。所以 pytest-multithreading 做了这个支持标记那些用例不并发运行的功能

使用示例如下:

import time

import pytest


test_data_list = [i for i in range(1,100)]
@pytest.mark.parametrize("i",test_data_list)
def test_multithreading(i):
    print("test_concurrent")

#被@pytest.mark.notconcurrent标记的用例不会参与并发运行,并发运行的用例会等这些被标记的用例运行结束后才开始并发运行
@pytest.mark.notconcurrent
def test_notconcurrent():
    print("test_notconcurrent")
    time.sleep(10)



if __name__ ==  "__main__":
    pytest.main(["test_pytest.py","-x","--th=100","-s"])

pytest-multithreading 与 pytest-parallel 的对比

一开始写 pytest-multithreading 的时候,是为了可以更高并发的运行 pytest 的用例。那时还不知道其实已经有 pytest-parallel 这个支持多线程运行用例的插件了。它们两个的对比如下:

1.pytest 的-x 参数失效了。pytest 原有的功能如果输入-x 参数时,如果有一个用例失败时,pytest 会立刻停止运行。但是启用了这两个插件后,pytes 会运行完所有用例。

2.启用这两个插件后,allure-pytest 生成的测试报告将无效

3.pytest-multithreading 比 pytest-parallel 有一个优点。pytest-paralle 运行 session 级别的 fixture。每个线程都会运行一次。这是和 pytest-xdist 同样的问题。而且如果 session 级别的 fixture 是有 IO 等待的话。pytest-paralle 执行用例的总时长将会大大增加

总结

虽然 pytest-multithreading 有以上缺点,但是我还是觉得它对我的工作是很有帮助的。因为我有几千个有 IO 等待的用例需要经常运行。这个时候 pytest-multithreading 能够最快的帮我运行完。总结起来说就是 pytest-multithreading 的适用场景是有很多有 IO 等待的用例需要快速运行。以后再找时间兼容下 allure-pytest 插件和-x 参数的问题


↙↙↙阅读原文可查看相关链接,并与作者交流