pytest测试框架系列 - Pytest pytest-xdist 分布式、多进程并发执行用例你会用吗?

前言

场景:随着项目越来越大、复杂,用例越来越多,串行的执行就需要太多的时间,就像测试部门一样,项目太多,项目完成的时间就越来越久,这就需要我们招聘更多的人,同时来测试项目,这样就提高了测试效率,但是需要尽量减少项目测试之间的关联性、耦合性。

Pytest 框架提供了一个pytest-xdist 插件帮我们做了这件事情,我们只需要简单的使用即可。

用例需要并发执行注意点

  • 每条用例是独立的,没有依赖关系,完全解耦,用例可以完全独立运行
  • 用例执行没有顺序,随机顺序都能正常执行
  • 每个用例都能重复运行,运行结果不会影响其他用例

pytest-xdist 详解 (建议掌握程度:☆☆☆☆☆)

安装

  • 在命令行窗口输入: pip install pytest-xdist
  • 查看安装版本:pip show pytest-xdist
    在这里插入图片描述

使用

使用方法 :

  • pytest -n num (代表使用num个CPU)
  • pytest -n auto
    • n auto:可以自动检测到系统的CPU核数;从测试结果来看,检测到的是逻辑处理器的数量
    • 使用auto等于利用了所有CPU来跑用例,此时CPU占用率会特别高

说明:建议最多使用1/2的CPU个数来进行执行,消耗资源太多,导致电脑太卡

先看下不使用分布式执行

# !/usr/bin/python3
# _*_coding:utf-8 _*_
""""
# @Time  :2021/7/10 13:31
# @Author  : king
# @File    :test_xdist.py
# @Software  :PyCharm
# @blog     :https://blog.csdn.net/u010454117
# @WeChat Official Account: 【测试之路笔记】
"""
import pytest
import time

def test_01():
    time.sleep(1)
    print("我是 test_01 用例")
    assert True

def test_02():
    time.sleep(1)
    print("我是 test_02 用例")
    assert True

def test_03():
    time.sleep(1)
    print("我是 test_03 用例")
    assert True

def test_04():
    time.sleep(1)
    print("我是 test_04 用例")
    assert True

def test_05():
    time.sleep(1)
    print("我是 test_05 用例")
    assert True

def test_06():
    time.sleep(1)
    print("我是 test_06 用例")
    assert True

def test_07():
    time.sleep(1)
    print("我是 test_07 用例")
    assert True

def test_08():
    time.sleep(1)
    print("我是 test_08 用例")
    assert True

def test_09():
    time.sleep(1)
    print("我是 test_09 用例")
    assert True

def test_10():
    time.sleep(1)
    print("我是 test_10 用例")
    assert True

def test_11():
    time.sleep(1)
    print("我是 test_11 用例")
    assert True

def test_12():
    time.sleep(1)
    print("我是 test_12 用例")
    assert True

if __name__ == '__main__':
    pytest.main(["-s", "-v"])

执行结果:代码每个用例sleep了1秒,可以看出来串行需要12秒,如果是成千上万的用例,需要的时间就特别长了
在这里插入图片描述
使用 pytest -n num
示例还是上面示例,直接看执行结果:命令输入pytest -n 3 test_xdist.py, 看执行时间是不是从12.20秒到4.75秒,是不是减少了2倍
在这里插入图片描述
使用 pytest -n auto
示例还是上面示例,直接看执行结果:命令输入pytest -n auto test_xdist.py,启动了8个进程,代表执行电脑总共8个虚拟CPU,因为用例不多,加上启动进程需要时间,所以跟3个进行消耗时间差不多,如果用例越多效果越明显,建议使用1/2的电脑CPU运行即可
在这里插入图片描述

看看多个文件时执行情况

  • test_xdist.pytest_xdist_02.pytest_xdist_03.py 里面代码 都是一样
  • 使用pytest -v -n 3 test_xdist.py test_xdist_02.py test_xdist_03.py 执行

执行结果:看结果是,先收集了所有用例,创建了3个执行器,分别执行对应的用例,3个执行器都是从第一个文件往后依次执行
在这里插入图片描述

问题:如果按照作用域分配给worker用例分别执行该怎么做

如果我们想要按照用例的作用域进行执行,该怎么处理呢?3个执行器只能分别执行一个模块(一个py文件)或者同一个文件里面同一个类只给一个执行器执行。

通过pytest-xdist的源码发现有这一段参数配置说明:

group.addoption(
        "--dist",
        metavar="distmode",
        action="store",
        choices=["each", "load", "loadscope", "loadfile", "no"],
        dest="dist",
        default="no",
        help=(
            "set mode for distributing tests to exec environments.\n\n"
            "each: send each test to all available environments.\n\n"
            "load: load balance by sending any pending test to any"
            " available environment.\n\n"
            "loadscope: load balance by sending pending groups of tests in"
            " the same scope to any available environment.\n\n"
            "loadfile: load balance by sending test grouped by file"
            " to any available environment.\n\n"
            "(default) no: run tests inprocess, don't distribute."
        ),

说明:

  • --dist=loadscope 将按照同一个作用域方法来分组,然后将每个测试组发给可以执行的worker,确保同一个组的测试用例在同一个进程中执行
  • --dist=loadfile 按照同一个文件名来分组,然后将每个测试组发给可以执行的worker,确保同一个组的测试用例在同一个进程中执行
  • --dist=each 是将每个用例,分别发给所有的执行器worker,相当于开了几个执行器worker,同一个用例就执行几遍
  • --dist=load 将待运行的用例随机发给可用的执行器worker,用例执行顺序随机的,目前默认采用这种方式

--dist=loadfile 示例:

示例代码还是上述代码,执行命令:pytest -v -n 3 --dist=loadfile test_xdist.py test_xdist_02.py test_xdist_03.py
在这里插入图片描述
结果:从结果可以看下 gw0 执行 test_xdist.py 模块, gw1 执行 test_xdist_02.py 模块, gw2 执行 test_xdist_03.py 模块

--dist=loadscope 示例:

test_xdist.py 示例代码:

# !/usr/bin/python3
# _*_coding:utf-8 _*_
""""
# @Time  :2021/7/10 13:31
# @Author  : king
# @File    :test_xdist.py
# @Software  :PyCharm
# @blog     :https://blog.csdn.net/u010454117
# @WeChat Official Account: 【测试之路笔记】
"""
import pytest
import time

class TestDist01:
    def test_01(self):
        time.sleep(1)
        print("我是 test_01 用例")
        assert True
      
    def test_02(self):
        time.sleep(1)
        print("我是 test_02 用例")
        assert True
    
    def test_03(self):
        time.sleep(1)
        print("我是 test_03 用例")
        assert True

class TestDist02:
    def test_04(self):
        time.sleep(1)
        print("我是 test_04 用例")
        assert True

    def test_05(self):
        time.sleep(1)
        print("我是 test_05 用例")
        assert True

    def test_06(self):
        time.sleep(1)
        print("我是 test_06 用例")
        assert True

class TestDist03:
    def test_07(self):
        time.sleep(1)
        print("我是 test_07 用例")
        assert True

    def test_08(self):
        time.sleep(1)
        print("我是 test_08 用例")
        assert True

    def test_09(self):
        time.sleep(1)
        print("我是 test_09 用例")
        assert True

class TestDist04:
    def test_10(self):
        time.sleep(1)
        print("我是 test_10 用例")
        assert True

    def test_11(self):
        time.sleep(1)
        print("我是 test_11 用例")
        assert True

    def test_12(self):
        time.sleep(1)
        print("我是 test_12 用例")
        assert True

if __name__ == '__main__':
    pytest.main()

执行结果
执行命令:pytest -v -n 3 --dist=loadscope test_xdist.py
在这里插入图片描述
结果:从结果可以看下 gw0 执行 test_xdist.py 模块的 TestDist01TestDist04 类, gw1 执行 test_xdist.py 模块的TestDist01 类, gw2 执行 test_xdist.py 模块的 TestDist03

--dist=each 示例:

与上述 test_xdist.py 示例代码一样,执行命令: pytest -v -n 3 --dist=each test_xdist.py
在这里插入图片描述
结果:从上面结果可以看出来,每天用例被执行了3遍

--dist=load--dist==no 示例:

  • 略,前面最开始执行示例,随机将待执行的用例分别给可用的执行器worker执行

总结

  • 使用并行测试 加上-n num 或者 -n auto 参数即可使用
  • 可以根据参数 --dist=loadfile--dist=loadscope--dist=each--dist=load--dist==no设置不同的执行器worker执行模式
  • 如果存在每条用例重复执行多次的场景,采用--dist=each模式,开几个执行器worker就执行几次

以上为内容纯属个人理解,如有不足,欢迎各位大神指正,转载请注明出处!

如果觉得文章不错,欢迎关注微信公众号,微信公众号每天推送相关测试技术文章
个人微信号

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

测试之路king

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值