Python 自动化测试(三): pytest 参数化测试用例构建

简介: 本文节选自霍格沃玆测试学院内部教材,文末链接进阶学习。在之前的文章中主要分享了 pytest 的实用特性,接下来讲 Pytest 参数化用例的构建。

本文节选自霍格沃玆测试学院内部教材,文末链接进阶学习。

在之前的文章中主要分享了 pytest 的实用特性,接下来讲 Pytest 参数化用例的构建。

如果待测试的输入与输出是一组数据,可以把测试数据组织起来用不同的测试数据调用相同的测试方法。参数化顾名思义就是把不同的参数,写到一个集合里,然后程序会自动取值运行用例,直到集合为空便结束。pytest 中可以使用 @pytest.mark.parametrize 来参数化。

使用 parametrize 实现参数化

parametrize( ) 方法源码:

def parametrize(self,argnames, argvalues, indirect=False, ids=None, \
    scope=None):
  • 主要参数说明

    • argsnames :参数名,是个字符串,如中间用逗号分隔则表示为多个参数名
    • argsvalues :参数值,参数组成的列表,列表中有几个元素,就会生成几条用例
  • 使用方法

    • 使用 @pytest.mark.paramtrize() 装饰测试方法
    • parametrize('data', param) 中的 “data” 是自定义的参数名,param 是引入的参数列表
    • 将自定义的参数名 data 作为参数传给测试用例 test_func
    • 然后就可以在测试用例内部使用 data 的参数了

创建测试用例,传入三组参数,每组两个元素,判断每组参数里面表达式和值是否相等,代码如下:

@pytest.mark.parametrize("test_input,expected",[("3+5",8),("2+5",7),("7*5",30)])
def test_eval(test_input,expected):
    # eval 将字符串str当成有效的表达式来求值,并返回结果
    assert eval(test_input) == expected

运行结果:

plugins: html-2.0.1, rerunfailures-8.0, xdist-1.31.0, ordering-0.6, \
forked-1.1.3, allure-pytest-2.8.11, metadata-1.8.0
collecting ... collected 3 items

test_mark_paramize.py::test_eval[3+5-8] 
test_mark_paramize.py::test_eval[2+5-7] 
test_mark_paramize.py::test_eval[7*5-35] 

============================== 3 passed in 0.02s ===============================

整个执行过程中,pytest 将参数列表 [("3+5",8),("2+5",7),("7*5",30)] 中的三组数据取出来,每组数据生成一条测试用例,并且将每组数据中的两个元素分别赋值到方法中,作为测试方法的参数由测试用例使用。

多次使用 parametrize

同一个测试用例还可以同时添加多个 @pytest.mark.parametrize 装饰器, 多个 parametrize 的所有元素互相组合(类似笛卡儿乘积),生成大量测试用例。

场景:比如登录场景,用户名输入情况有 n 种,密码的输入情况有 m 种,希望验证用户名和密码,就会涉及到 n*m 种组合的测试用例,如果把这些数据一一的列出来,工作量也是非常大的。pytest 提供了一种参数化的方式,将多组测试数据自动组合,生成大量的测试用例。示例代码如下:

@pytest.mark.parametrize("x",[1,2])
@pytest.mark.parametrize("y",[8,10,11])
def test_foo(x,y):
    print(f"测试数据组合x: {x} , y:{y}")

运行结果:

plugins: html-2.0.1, rerunfailures-8.0, xdist-1.31.0, ordering-0.6,\
 forked-1.1.3, allure-pytest-2.8.11, metadata-1.8.0
collecting ... collected 6 items

test_mark_paramize.py::test_foo[8-1] 
test_mark_paramize.py::test_foo[8-2] 
test_mark_paramize.py::test_foo[10-1] 
test_mark_paramize.py::test_foo[10-2] 
test_mark_paramize.py::test_foo[11-1] 
test_mark_paramize.py::test_foo[11-2] 

分析如上运行结果,测试方法 test_foo( ) 添加了两个 @pytest.mark.parametrize() 装饰器,两个装饰器分别提供两个参数值的列表,2 * 3 = 6 种结合,pytest 便会生成 6 条测试用例。在测试中通常使用这种方法是所有变量、所有取值的完全组合,可以实现全面的测试。

@pytest.fixture 与 @pytest.mark.parametrize 结合

下面讲结合 @pytest.fixture 与 @pytest.mark.parametrize 实现参数化。

如果测试数据需要在 fixture 方法中使用,同时也需要在测试用例中使用,可以在使用 parametrize 的时候添加一个参数 indirect=True,pytest 可以实现将参数传入到 fixture 方法中,也可以在当前的测试用例中使用。

parametrize 源码:

def parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None):

indirect 参数设置为 True,pytest 会把 argnames 当作函数去执行,将 argvalues 作为参数传入到 argnames 这个函数里。创建“test_param.py”文件,代码如下:

# 方法名作为参数
test_user_data = ['Tome', 'Jerry']
@pytest.fixture(scope="module")
def login_r(request):
    # 通过request.param获取参数
    user = request.param
    print(f"\n 登录用户:{user}")
    return user

@pytest.mark.parametrize("login_r", test_user_data,indirect=True)
def test_login(login_r):
    a = login_r
    print(f"测试用例中login的返回值; {a}")
    assert a != ""

运行结果:

plugins: html-2.0.1, rerunfailures-8.0, xdist-1.31.0, ordering-0.6,\
 forked-1.1.3, allure-pytest-2.8.11, metadata-1.8.0
collecting ... collected 2 items

test_mark_paramize.py::test_login[Tome] 
test_mark_paramize.py::test_login[Jerry] 

============================== 2 passed in 0.02s ===============================

Process finished with exit code 0

 登录用户:Tome PASSED           [ 50%]测试用例中login的返回值; Tome

 登录用户:Jerry PASSED           [100%]测试用例中login的返回值; Jerry

上面的结果可以看出,当 indirect=True 时,会将 login_r 作为参数,test_user_data 被当作参数传入到 login_r 方法中,生成多条测试用例。通过 return 将结果返回,当调用 login_r 可以获取到 login_r 这个方法的返回数据。

更多技术文章分享及测试资料点此获取

相关文章
|
9月前
|
敏捷开发 测试技术 API
测试金字塔:构建高效自动化测试策略的基石
测试金字塔:构建高效自动化测试策略的基石
633 116
|
9月前
|
测试技术 API 数据库
测试金字塔:构建高效自动化测试策略的基石
测试金字塔:构建高效自动化测试策略的基石
650 114
|
9月前
|
设计模式 前端开发 测试技术
告别脆弱:构建稳定UI自动化测试的3个核心策略
告别脆弱:构建稳定UI自动化测试的3个核心策略
813 113
|
9月前
|
JSON 监控 API
n8n错误处理全攻略:构建稳定可靠的自动化工作流
在n8n自动化工作流中,错误是提升系统可靠性的关键。本文详解常见错误类型、节点级与全局处理机制,结合重试、熔断、补偿事务等高级模式,助您构建稳定、可维护的生产级自动化流程。
|
9月前
|
Java 项目管理 Maven
Maven项目管理与构建自动化完全指南
Maven彻底改变了Java项目管理方式,通过POM模型、依赖管理和标准化构建流程,大幅提升开发效率。本文深入解析其核心概念、多模块管理、私服搭建及与Spring Boot、Docker等现代技术栈的集成实践,助力开发者实现高效、规范的项目构建与团队协作。
1298 156
Maven项目管理与构建自动化完全指南
数据采集 Web App开发 人工智能
553 0
|
11月前
|
人工智能 自然语言处理 安全
Milvus x n8n :自动化拆解Github文档,零代码构建领域知识智能问答
本文介绍了在构建特定技术领域问答机器人时面临的四大挑战:知识滞后性、信息幻觉、领域术语理解不足和知识库维护成本高。通过结合Milvus向量数据库和n8n低代码平台,提出了一种高效的解决方案。该方案利用Milvus的高性能向量检索和n8n的工作流编排能力,构建了一个可自动更新、精准回答技术问题的智能问答系统,并介绍了部署过程中的可观测性和安全性实现方法。
1255 0
|
11月前
|
机器学习/深度学习 存储 算法
Trinity-RFT:构建智能体持续学习的自动化强化微调工厂
大型语言模型作为智能体在真实环境中持续交互学习面临诸多挑战。 Trinity-RFT 是通义实验室推出的强化微调框架,旨在实现智能体的持续进化。它通过探索、训练与经验池的解耦设计,支持多样化训练模式,提升资源利用率和学习稳定性。同时,Trinity-RFT 提供灵活的数据处理与算法模块化功能,降低应用与研究门槛,助力迈向终身学习与自主进化的智能体时代。
1039 2
|
12月前
|
XML Java 数据库连接
MyBatis Generator插件使用详解:自动化构建效率提升
总体来说,MyBatis Generator的使用可以显著提高数据访问层代码的编写效率,减少出错概率,并为团队统一代码风格提供便捷。在面对要求快速发展和迭代的软件项目时,MBG的自动化代码生成功能成了不可或缺的辅助工具。
309 0
|
存储 人工智能 运维
企业级MLOps落地:基于PAI-Studio构建自动化模型迭代流水线
本文深入解析MLOps落地的核心挑战与解决方案,涵盖技术断层分析、PAI-Studio平台选型、自动化流水线设计及实战构建,全面提升模型迭代效率与稳定性。
617 6

推荐镜像

更多