【pytest】pytest -@pytest.mark.parametrize` 装饰器-参数化测试功能

目录

基础概念及简单示例

pytest 的参数化测试功能允许我们为相同的测试函数提供多组不同的输入数据和预期输出,从而确保在各种情况下测试逻辑的正确性。这大大增强了测试的健壮性和覆盖率,特别是当测试逻辑需要处理多种边界条件或输入变化时。

要使用 pytest 的参数化测试功能,你需要使用 @pytest.mark.parametrize 装饰器。这个装饰器接受两个参数:一个字符串,表示测试函数参数的名称;一个值列表,其中每个值都是一组输入数据(通常是一个元组或列表)。

下面是一个简单的例子,演示了如何使用参数化测试来验证一个简单的加法函数:

python 复制代码
# content of test_example.py

def add(x, y):
    return x + y

# 使用 @pytest.mark.parametrize 进行参数化测试
@pytest.mark.parametrize("x, y, expected", [
    (1, 2, 3),
    (0, 0, 0),
    (-1, 1, 0),
    (1.5, 1.5, 3.0),
])
def test_add(x, y, expected):
    assert add(x, y) == expected

在这个例子中,test_add 函数会运行四次,每次使用 @pytest.mark.parametrize 装饰器中提供的一组不同的 (x, y, expected) 值。每次运行时,xy 是输入参数,expected 是期望的返回结果。测试函数通过 assert 语句来验证 add(x, y) 的结果是否等于 expected

当你运行这个测试文件时(例如,通过命令行 pytest test_example.py),你会看到四个测试案例的结果。如果所有案例都通过,那么你的加法函数就针对这些输入数据进行了充分的验证。

参数化测试特别适用于测试那些接受多种不同类型输入或需要处理多种边界条件的函数。通过使用参数化测试,你可以确保你的代码在各种情况下都能正常工作,从而提高代码的质量和可靠性。

实例

当然可以,下面是一个更复杂的例子,它展示了如何使用 pytest 的参数化测试功能来测试一个处理用户输入的函数。这个函数负责验证输入,并根据不同的输入返回不同的结果。

假设我们有一个函数 process_user_input,它接受一个字符串作为输入,并根据输入内容返回相应的处理结果:

python 复制代码
# user_processor.py

def process_user_input(input_string):
    if input_string.lower() == 'yes':
        return 'User confirmed.'
    elif input_string.lower() == 'no':
        return 'User declined.'
    elif input_string.isdigit():
        return f'You entered a number: {int(input_string)}'
    else:
        raise ValueError('Invalid input.')

现在,我们想要测试这个函数以确保它对于不同的输入能够返回正确的结果,并且在遇到无效输入时能够抛出异常。我们可以使用 pytest 的参数化测试功能来编写多个测试用例:

python 复制代码
# test_user_processor.py

import pytest
from user_processor import process_user_input

# 参数化测试数据
test_data = [
  # 测试输入 'yes' 时,期望返回 'User confirmed.'  
    ('yes', 'User confirmed.'),
    ('NO', 'User declined.'),  # 注意这里大小写应该不敏感
    ('123', 'You entered a number: 123'),
 # 测试输入无效字符串 'abc' 时,期望抛出 ValueError 异常
    ('abc', pytest.raises(ValueError)),  # 预期抛出异常
    ('', pytest.raises(ValueError)),      # 空字符串也是无效输入
    ('   ', pytest.raises(ValueError)),    # 空格也是无效输入
]

# 使用 @pytest.mark.parametrize 装饰器,将测试数据参数化到测试函数中  
@pytest.mark.parametrize("input_string, expected_result", test_data)  
def test_process_user_input(input_string, expected_result):  
    # 检查期望结果是否是异常类型  
    if isinstance(expected_result, type):  
        # 如果是异常类型,使用 pytest.raises 上下文管理器来断言函数会抛出该异常  
        with pytest.raises(expected_result):  
            process_user_input(input_string)  
    else:  
        # 如果不是异常类型,使用 assert 语句来断言函数的返回值与期望结果匹配  
        assert process_user_input(input_string) == expected_result  
  
# 运行测试时,pytest 会自动找到并执行此文件中的测试函数

在这个例子中,test_data 是一个包含多组测试数据的列表,每组数据都是一个元组,其中包含输入字符串和期望的结果。对于期望抛出异常的测试用例,我们使用 pytest.raises 作为期望结果。

test_process_user_input 函数使用 @pytest.mark.parametrize 装饰器来接收这些测试数据,并针对每一组数据运行一次测试。在测试函数中,我们首先检查 expected_result 是否是一个异常类型;如果是,我们使用 pytest.raises 上下文管理器来断言函数会抛出该异常。如果 expected_result 不是异常类型,我们则使用 assert 语句来断言函数的返回值与期望结果相匹配。

运行这个测试文件(例如,通过命令行 pytest test_user_processor.py),pytest 会为 test_process_user_input 函数中的每一组测试数据运行一次测试,并报告结果。这允许我们全面验证 process_user_input 函数在各种情况下的行为。

相关推荐
诚威_lol_中大努力中2 分钟前
关于pytorch3d的安装
人工智能·pytorch·python
GISer_Jing8 分钟前
神经网络、深度学习、卷积神经网络
python
Suwg20916 分钟前
《手写Mybatis渐进式源码实践》实践笔记(第七章 SQL执行器的创建和使用)
java·数据库·笔记·后端·sql·mybatis·模板方法模式
丁总学Java19 分钟前
优化 invite_codes 表的 SQL 创建语句
java·数据库·sql
hmbbpdx33 分钟前
MySql B树 B+树
数据库·b树·mysql
小王子102440 分钟前
数据结构与算法Python版 二叉查找树
数据结构·python·算法·二叉查找树
编程阿布1 小时前
Python基础——多线程编程
java·数据库·python
冰镇毛衣1 小时前
4.5 数据表的外连接
数据库·sql·mysql
又蓝1 小时前
使用 Python 操作 MySQL 数据库的实用工具类:MySQLHandler
数据库·python·mysql
dundunmm1 小时前
机器学习之pandas
人工智能·python·机器学习·数据挖掘·pandas