【pytest进阶】如何分布式执行接口自动化测试用例

一、写在前面

随着UCS PaSS的OpenAP接口越来越多,相对应接口自动化用例数量也越来越多(截止于2022/07/20 19:51:30 UCS接口用例已达5001条),在可预见的未来,必定会不断增加。因此,需提升接口自动化用例的执行效率或更改执行策略。执行策略自然业务组更需考虑,自动化组需在执行效率方面”挖潜增效”,需提前进行技术的预研。

当前测试套为单进程执行,只能用到执行节点的单核资源;如果能实现单服务器多核多进程或多服务器多进行执行,是否就能实现分布式执行接口自动化用例,执行效率就能成倍提升?万幸的是,我们选用的pytest测试框架,pytest的特性以及整个接口测试套低耦合、高内聚的设计,让该设想成为可能。

首先,介绍下分布式测试用例的设计原则:

(1)独立运行:用例之间是独立的,并没有依赖关系,还可以完全独立运行;

(2)随机执行:用例执行不强制按顺序执行,支持顺序执行或随机执行

(3)不影响其他用例:每个用例都能重复执行,运行结果不会影响其他用例。

然后,我们再回过头来看看我们的测试套Jenkins构建,支持任意选择模块、跳过任意用例点执行,完全符合分布式测试用例独立运行、随机运行、不影响其他用例原则。不得不感叹,最初设计测试套时的前瞻性。

既然接口自动化用例已经符合分布式的原则了,接下来就交给pytest的pytest-xdist插件,一个能实现进程级别并发。pytest-xdist通过一些独特的测试执行模式扩展了pytest:

(1)测试运行并行化:如果有多个CPU或主机,则可以将它们用于组合测试执行。这样可以加快开发速度或使用远程计算机的特殊资源。

(2)–looponfail:在子进程中重复运行执行每次运行之后,pytest 都会等到项目中的文件更改后再运行之前失败的测试。重复此过程,直到所有测试通过,然后再次执行完整运行。

(3)跨平台覆盖:可以指定不同的 Python 解释器或不同的平台,并在所有这些平台上并行运行测试。

二、如何安装

在命令行中运行以下命令进行安装:

pip install pytest-xdist

或者(使用国内的豆瓣源,数据会定期同步国外官网,速度快。)

pip install pytest-xdist -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

三、示例

创建一个xdistTest项目,项目内新增test_xdist.py、test_xdist01.py、test_xdist02.py三个文件.

test_xdist.py代码如下:

#!/usr/bin/python3
-*- coding: UTF-8 -*-

import requests
import pytest

class Testxdist(object):
    def test_tmall_001(self):
        print("1233da")
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_002(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_003(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_004(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_005(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_006(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_007(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_008(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_009(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_010(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_011(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_012(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_013(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_014(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_015(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_016(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_017(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_018(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_019(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_020(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_021(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

test_xdist01.py代码如下:

#!/usr/bin/python3
-*- coding: UTF-8 -*-

import requests
import pytest

class Testxdist01(object):
    def test_tmall_022(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_023(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_024(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_025(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_026(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_027(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_028(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_029(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_030(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_031(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_032(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_033(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_034(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_035(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_036(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_037(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_038(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_039(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_040(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_041(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_042(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

test_xdist02.py代码如下:

#!/usr/bin/python3
-*- coding: UTF-8 -*-

import requests
import pytest

class Testxdist02(object):

    def test_tmall_043(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_044(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_045(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_046(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_047(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_048(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_049(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_050(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_051(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_052(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_053(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_054(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_055(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_056(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_057(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_058(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_059(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_060(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_061(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_062(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

    def test_tmall_063(self):
        r = requests.get(url="https://www.tmall.com")
        print(r.elapsed.total_seconds())

整体代码非常的简单,test_xdist.py、test_xdist01.py、test_xdist02.py累积一共63个访问天猫的test_xxx函数,各用例函数之间彼此独立。

(1)如果不使用分布式测试用例,打开命令行,在该项目根目录下,输入pytest -s -v命令执行,63条用例执行耗时20.85s,执行结果如下:

【pytest进阶】如何分布式执行接口自动化测试用例

(2)使用pytest-xdist分布式测试执行测试用例

参数-n auto :可以自动检测系统的CPU核数

注意:使用auto等于利用了所有CPU来跑用例,此时CPU占用率会特别高。如果指定核数可将auto替换为具体的数字

分布式执行在根目录下输入执行命令:pytest -s -v -n auto,执行63条用例耗时3.71s,执行结果如下:

【pytest进阶】如何分布式执行接口自动化测试用例

很明显,分布式执行用例,执行效率有了质的飞跃。

写到这里,已经过8:30了,该下班跑路了。下期我们解密pytest-xdist的原理以及其他重要的使用注意事项!

Original: https://blog.csdn.net/Heney33/article/details/125899460
Author: Heney33
Title: 【pytest进阶】如何分布式执行接口自动化测试用例

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/773098/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球