使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 18--测试框架Pytest基础 2--插件和参数化

作者:我的xiaodoujiao日期:2025/10/19

测试学习记录,仅供参考!

Pytest 框架

七、pytest 丰富的插件系统

可以去安装外部的插件,去使用 pytest 来执行插件;这就是为什么选择使用 pytest 框架的原因,因为 pytest 里面有丰富的插件系统,而 unittest 是没有这些插件的;所以 pytest 要比 unittest 测试框架更加灵活;

例如:

当测试用例很多的时候,可以使用并发执行,可以使用多进程/多线程去执行测试用例,提高测试效率;

测试用例失败重跑插件;在执行测试用例时,由于网络波动、硬件设备等不确定的因素,导致执行测试用例失败,但并不是测试结果测试失败的情况下,可以用到重试运行失败用例重跑的插件;

执行测试用例顺序的插件、生成测试报告的插件、数据参数化等等;

第一个、并发执行(多进程/多线程)

pytest-xdist 提供一个 -n 参数选项设置多进程/线程数量,去设置多少个线程去执行测试用例;使得测试用例可以在多个进程或线程中并发执行,提供测试效率;

安装插件

pip install pytest-xdist

在 main 函数中设置进程数;

命名行

pytest test_plug_in.py -n 3

配置文件 pytest.ini 中设置,然后再运行 run.py 主方法函数文件;
1[pytest]
2addopts = -vs -n 3
3
4testpaths = ./testcase
5; testpaths = ./other
6
7python_files = test_*.py
8
9python_classes = Test*
10
11python_functions = test_*
第二个、测试用例失败重跑

安装插件

pip install pytest-rerunfailures

模拟场景

定义一个 class TestReRunFailed: 测试类 ;

定义一个 def test_rerun_fail_case(self): 方法;

模拟偶发性失败、或是环境因素导致的测试失败;

写一个随机数随机执行,再断言随机选择“随机真值、假值”,然后去执行;

怎么使用失败重跑插件
对单个测试用例设置失败重跑次数

去关注平时跑的测试用例,哪一个用例波动比较大的,可以在那一个测试用例的前面添加 @pytest.mark.flaky() 装饰器,去设置重跑次数,里面需要用到两个参数,第一个 reruns=3 参数是当用例失败时会重跑次数(指定失败时重跑的次数),第二个 reruns_delay=2 参数是指定重试之间的延迟时间;这是对单个测试用例去设置重跑的次数;,根据平时跑的一个结果,去判定哪条测试用例报错比较多,就在那条测试用例加上失败重跑调试;

代码演示:

1import pytest
2
3class TestReRunFailed:
4
5    @pytest.mark.flaky(reruns=3, reruns_delay=2)
6    def test_rerun_fail_case(self):
7        import random
8        assert random.choice([True, False])
9
10    def test_rerun_fail_case02(self):
11        import random
12        assert random.choice([True, False])
13
14if __name__ == '__main__':
15    pytest.main()
16    # pytest.main(['--reruns=3'])    
对所有测试用例设置失败重跑次数

在 pytest.ini 配置文件中去设置测试用例失败重跑参数,为所有的测试用例默认加上失败重跑的次数;

1[pytest]
2addopts = -vs --reruns 3
3
4testpaths = ./testcase
5
6python_files = test_*.py
7
8python_classes = Test*
9
10python_functions = test_*
第三个、测试用例执行顺序

因为在默认情况下,pytest 会以特定的顺序运行测试用例;可以使用 pytest-ordering 插件去自定义设置测试用例的执行顺序;

通常是按照测试文件中定义的顺序去执行,但是有的时候,测试用例的执行顺序对于特定的场景可能很重要,此时就需要更加精细的去控制测试用例的执行顺序;比如要去删除某一个用户,这种情况首先得先去跑执行新增创建用户的用例,只有新增完成之后,才能有数据去调用删除接口;

安装插件,通过插件去改变测试用例的执行顺序;

pip install pytest-ordering

第一种写法

通过 pytest 装饰器 @pytest.mark.run(order=4) 调用插件里面的 run 方法来设置执行顺序;

1import pytest
2
3class TestOrdering:
4    @pytest.mark.run(order=4)
5    def test_ordering_case_01(self):
6        print('第一个测试用例')
7
8    @pytest.mark.run(order=5)
9    def test_ordering_case_02(self):
10        print('第二个测试用例')
11
12    @pytest.mark.run(order=1)
13    def test_ordering_case_03(self):
14        print('第三个测试用例')
15
16    @pytest.mark.run(order=2)
17    def test_ordering_case_04(self):
18        print('第四个测试用例')
19
20    @pytest.mark.run(order=3)
21    def test_ordering_case_05(self):
22        print('第五个测试用例')
23
24
25if __name__ == '__main__':
26    pytest.main()

注意:当编号相同时,就根据文件设置的编码去执行了;

第二种写法、通过自定义方式
1import pytest
2
3
4class TestOrdering:
5    @pytest.mark.last
6    def test_ordering_case_01(self):
7        print('第一个测试用例')
8
9    @pytest.mark.first
10    def test_ordering_case_02(self):
11        print('第二个测试用例')
12
13    @pytest.mark.second
14    def test_ordering_case_03(self):
15        print('第三个测试用例')
16
17
18if __name__ == '__main__':
19    pytest.main()

运行后若发现警告信息(大致意思是“pytest 识别到了未注册的自定义标记”,如果使用的自定义标记不是 pytest 中自带的,而是个人自定义的时候就会出现警告信息),可以通过在 pytest.ini 配置文件中使用 markers 注册自定义标记来消除警告信息;

1[pytest]
2addopts = -vs --reruns 3
3
4testpaths = ./testcase
5
6python_files = test_*.py
7
8python_classes = Test*
9
10python_functions = test_*
11
12markers =
13    last
14    first
15    second

第四个、测试报告 allure-pytest

后续介绍。。。

八、参数化处理

在 pytest 中,参数化处理是最重要的部分之一,在实际工作场景中会经常用到,测试某一个功能时,需要传参数,才能去校验准确性;参数化是一种测试用例复用的方法,允许在一个测试函数上运行多组输入数据,以覆盖不同的测试场景,参数化使用 @pytest.mark.parametrize 装饰器来实现;

1、参数化的基本用法

使用 @pytest.mark.parametrize 装饰器,通过装饰器将参数传递给测试函数;

指定参数名和参数值;

在测试函数的参数中接收参数值,用于运行多次测试;

语法:@pytest.mark.parametrize("params1,params2,params3...",params_value)

params:参数值,可接收多个;

params_value:任何可迭代的对象,例如“列表、集合、字典等”

2、代码实现

参数化时会把“可迭代对象”里面的数据传递给“可接收参数”;

例如 可迭代对象 列表中 ['python', 'java', 'C#'] 有三组数据,参数化时会把 这三组数据 传递给 可接收参数 params;然后在测试函数中接收参数 def test_params_01(self, params): 在测试函数里面去接收参数化传递过来的值,这两个值(params)要一样,不能变,就是 @pytest.mark.parametrize 装饰器中的第一个参数 params 要和测试函数中接收的参数 params 一致;

接收单个参数
1import pytest
2
3class TestParams:
4
5    @pytest.mark.parametrize("params", ['python', 'java', 'C#'])
6    def test_params_01(self, params):
7        print(params)

运行 run.py 主函数文件,查看 test_params_01 测试方法能不能接收到 @pytest.mark.parametrize 装饰器参数化传递的参数;

可以看到 test_params_01 这一个测试用例成功执行了三次;

接收多个参数

接收多个参数时,注意相互对应,最好数据个数和接收参数个数相同;

可迭代对象:列表
1import pytest
2
3class TestParams:
4
5    @pytest.mark.parametrize("username,password", [("test01", "qwe123"), ("test02", "qwe456"), ("test03", "qwe789")])
6    def test_login_case(self, username, password):
7        print(f"用户名:{username},密码:{password}")

可迭代对象:集合
1import pytest
2
3class TestParams:
4
5    @pytest.mark.parametrize("params", ['python', 'java', 'C#'])
6    def test_params_01(self, params):
7        print(params)
8
9    @pytest.mark.parametrize("username,password", [("test01", "qwe123"), ("test02", "qwe456"), ("test03", "qwe789")])
10    def test_login_case(self, username, password):
11        print(f"用户名:{username},密码:{password}")
12
13    @pytest.mark.parametrize("usernames,passwords", {("test001", "qwe0123"), ("test002", "qwe0456"), ("test003", "qwe0789")})
14    def test_login_case_02(self, usernames, passwords):
15        print(f"用户名:{usernames},密码:{passwords}")

可迭代对象:字典

字典的迭代对象是只迭代 key 值,所以使用一个参数去接收;一般很少使用这种场景;

1import pytest
2
3class TestParams:
4
5    @pytest.mark.parametrize("params", ['python', 'java', 'C#'])
6    def test_params_01(self, params):
7        print(params)
8
9    @pytest.mark.parametrize("username,password", [("test01", "qwe123"), ("test02", "qwe456"), ("test03", "qwe789")])
10    def test_login_case(self, username, password):
11        print(f"用户名:{username},密码:{password}")
12
13    @pytest.mark.parametrize("usernames,passwords,address",
14                             {("test001", "qwe0123", "BJ"), ("test002", "qwe0456", "SH"), ("test003", "qwe0789", "SZ")})
15    def test_login_case_02(self, usernames, passwords, address):
16        print(f"用户名:{usernames},密码:{passwords},地址:{address}")
17
18    @pytest.mark.parametrize("user_name", {"test0001": "qwe00123", "test0002": "qwe00456"})
19    def test_login_case_03(self, user_name):
20        print(f"用户名:{user_name}")
21

后续把参数化中的参数改造成可读取文件中的数据(例如 yaml 文件、Excel 文件等等)

未完待续。。。


使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 18--测试框架Pytest基础 2--插件和参数化》 是转载文章,点击查看原文


相关推荐


从零构建量化学习工具:动量策略(Momentum Strategy)
叶梅树2025/10/18

知识点介绍 动量策略是量化交易的核心知识点之一,它基于“强者恒强、弱者恒弱”的市场假设:过去表现好的资产(价格上涨)未来继续上涨,表现差的继续下跌。核心公式:动量 = (当前价 - N期前价) / N期前价(N通常12月/20日)。交易规则:动量>0买入、<0卖出,或排名选TopK股。 优势:简单有效,捕捉趋势(A股牛市强)。缺点:趋势反转时大回撤(如2022熊市)。入门公式:Sharpe比率 = (策略收益 - 无风险率) / 波动率(>1好)。实践:用历史数据回测,结合RSI避超买。 案例说


Jmeter分布式集群搭建与使用
晚笛诶2025/10/16

目录 一、JMeter 简介 核心功能 主要特点 二、JMeter插件扩展安装 三、JMeter分布式集群环境搭建 Jmeter分布式原理: 原理图: 主控机与负载机通信 测试执行流程 环境配置: 配置分布式测试环境 第一种测试机部署在不同的服务器上: 测试机配置: 主控机配置: 第二种测试机通过docker部署在同一台服务器上: 测试机配置: 主控机配置: 一、JMeter 简介 JMeter 是一款开源的性能测试工具,由 Apache 软件基金会


PyQt5 QTreeWidget 深度解析:树形列表框的完整指南
三雷科技2025/10/15

PyQt5 QTreeWidget 深度解析:树形列表框的完整指南 1. QTreeWidget 概述与设计哲学 1.1 什么是 QTreeWidget? QTreeWidget 是 PyQt5 中用于显示层次化数据的高级控件,它继承自 QTreeView,提供了一个基于项目的树形视图。与平面列表不同,QTreeWidget 能够直观地展示父子关系,非常适合文件系统、组织结构、分类数据等层次化信息的展示。 核心设计理念:QTreeWidget 的设计遵循了"层次化数据展示"原则,通过树形


Easysearch 冷热架构实战
极限实验室2025/10/14

在之前的文章中,我们介绍了如何使用索引生命周期策略来管理索引。如果要求索引根据其生命周期阶段自动在不同的节点之间迁移,还需要用到冷热架构。我们来看看具体如何实现。 冷热架构 冷热架构其实就是在 Easyearch 集群中定义不同属性的节点,这些节点共同组成冷热架构。比如给所有热节点一个 hot 属性,给所有冷节点一个 cold 属性。在 Easyearch 中分配节点属性是通过配置文件(easysearch.yml)来实现的,比如我要定义一个热节点和一个冷节点,我可以在对应节点的配置文件中添加如


如何设计一个架构良好的前端请求库?
sorryhc2025/10/12

一、写在前面(抛出思考题) 过去的时间,你刷遍了面试题,在公司中工作了很多年,基于axios二次封装单项目级别的请求文件手到擒来。 你有没有想过?你是一个前端团队的资深老人,随着公司业务不断发展,各种各样的前端项目用着不同的请求技术方案。 A项目比较老,用的xhr; B项目用了axios,拥抱开源; C项目因为小王拥抱原生的理念,使用了fetch; 现在团队需要技术标准化,统一前端请求方案,将所有的请求集成到一个包里,如何设计技术方案,可以让这个包很健壮,未来很好维护? 这其实和大公司业务面广的


C/C++黑客帝国代码雨
Want5952025/10/10

写在前面 数字雨,又被称为“黑客帝国雨”,是一种经典的视觉效果,常用于表现科幻、科技感十足的场景。这种效果最初在电影《黑客帝国》中出现,以绿色字符从屏幕顶端不断下落的方式,营造出一种神秘而充满未来感的氛围。本文将介绍如何使用C语言在Windows控制台中实现一个简易的数字雨效果。通过这篇文章,你不仅能了解如何利用控制台API进行绘图操作,还能体会到字符动画背后的技术逻辑与美感。 系列文章 序号直达链接1C/C++李峋同款跳动的爱心2C/C++跳动的爱心3C/C++经典爱心4C/C++满


深入浅出 Compose 测量机制
Pika2025/10/9

自从换了新工作后,好久没有写博客了,今天终于能有时间写点东西,Compose作为Android新一代UI框架,已经得到了很多公司的认可,未来市场对Compose的要求也逐步提高。如果大家对Compose有兴趣,也欢迎后台私信我,字节移动OS招聘Compose框架的二次定制开发的Android小伙伴,一起把Compose做大做强吧! UI框架的测量流程 对于UI框架来说,测量布局与绘制可谓是非常重要的三个话题,对于Compose来说也不例外,本章我们将从着Compose的原理出发,来聊一下最重要


大数据毕业设计选题推荐-基于大数据的全球产品库存数据分析与可视化系统-大数据-Spark-Hadoop-Bigdata
IT研究室2025/10/8

✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python项目 安卓项目 微信小程序项目 文章目录 一、前言二、开发环境三、系统界面展示四、代码参考五、系统视频结语 一、前言 系统介绍 本系统是一个基于大数据技术的全球产品库存数据分析与可视化系统,采用Hado


【Linux】线程的互斥
羚羊角uou2025/10/6

因为线程是共享地址空间的,就会共享大部分资源,这种共享资源就是公共资源,当多执行流访问公共资源的时候,就会出现各种情况的数据不一致问题。为了解决这种问题,我们就需要学习线程的同步与互斥,本篇将介绍线程的互斥。 1.相关概念 临界资源:多线程执⾏流被保护的共享资源就叫做临界资源 临界区:每个线程内部,访问临界资源的代码,就叫做临界区 互斥:任何时刻,互斥保证有且只有⼀个执⾏流进⼊临界区,访问临界资源,通常对临界资源起保护作⽤ 原⼦性:不会被任何调度机制打断的操作,该操作只有两态,要么完成,


MySQL Performance Schema详解与实战应用
IT橘子皮2025/10/5

Performance Schema是MySQL内置的性能监控系统,自5.5版本引入以来已成为数据库性能分析与优化的核心工具。本文将全面解析其架构原理、配置方法及典型应用场景,帮助您掌握这一强大的性能诊断利器。 一、Performance Schema核心架构 Performance Schema采用插桩-消费者模型构建,通过轻量级的内存表存储性能数据,对数据库性能影响通常控制在5%以内。其核心组件包括: ​插桩点(Instruments)​​:嵌入MySQL代码的探测点,按层级命名如wai

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0