Pytest 高级用法:间接参数化

文章目录

    • [1. 引言](#1. 引言)
    • [2. 基础概念](#2. 基础概念)
      • [2.1 Fixture](#2.1 Fixture)
      • [2.2 参数化](#2.2 参数化)
    • [3. 代码实例](#3. 代码实例)
      • [3.1 基础设置](#3.1 基础设置)
      • [3.2 测试用例示例](#3.2 测试用例示例)
        • [示例 1:基础的间接参数化](#示例 1:基础的间接参数化)
        • [示例 2:通过 request 获取参数值](#示例 2:通过 request 获取参数值)
        • [示例 3:多参数组合测试](#示例 3:多参数组合测试)
        • [示例 4:部分间接参数化](#示例 4:部分间接参数化)
    • [4. 最佳实践](#4. 最佳实践)
    • [5. 总结](#5. 总结)
    • 参考资料

1. 引言

在进行单元测试时,我们经常需要使用不同的参数来测试同一个功能。Pytest 提供了强大的参数化功能,并且可以与 fixture 结合使用,使得测试代码更加灵活和可维护。本文将深入探讨 pytest 中参数化和 fixture 的高级用法。

2. 基础概念

2.1 Fixture

Fixture 是 pytest 中的一个核心概念,它提供了一种方式来为测试提供可复用的依赖。Fixture 可以:

  • 提供测试数据
  • 设置测试环境
  • 处理测试资源的创建和清理

2.2 参数化

参数化允许我们使用不同的参数多次运行同一个测试。pytest 提供了两种主要的参数化方式:

  • 直接参数化:参数直接传递给测试函数
  • 间接参数化:参数通过 fixture 传递给测试函数

3. 代码实例

3.1 基础设置

首先,我们需要创建两个文件:conftest.pytest_fixture_indirect.py

python 复制代码
# conftest.py
import pytest

@pytest.fixture(scope='module')
def fixture_indirect(request):
    print(f"fixture_indirect, request: {request}")
    print(f"fixture_indirect, request.param: {request.param}")
    var = 'var_from_fixture_indirect'
    yield var

@pytest.fixture(scope='module')
def fixture_direct(request):  # request 参数可选
    print(f"fixture_direct, request: {request}")
    var = 'var_from_fixture_direct'
    yield var

3.2 测试用例示例

示例 1:基础的间接参数化
  • 使用 indirect=True 表示参数会传递给同名的 fixture
  • fixture 会接收到参数值,但测试函数只能获得 fixture 的返回值
python 复制代码
@pytest.mark.parametrize("fixture_indirect", [110, 120], indirect=True)
def test_fixture_indirect(fixture_indirect):
    print(f"Case fixture_indirect: {fixture_indirect}")
    # 注意:这里无法直接访问参数值 110, 120

"""
会运行两次测试,每次:
- 先执行 fixture_indirect,获得参数 110/120
- 然后运行测试函数,得到 fixture 的返回值
"""
复制代码
fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect[110]>>
fixture_indirect, request.param: 110
PASSED          [ 50%]
Case fixture_indirect: var_from_fixture_indirect

fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect[120]>>
fixture_indirect, request.param: 120
PASSED          [100%]
Case fixture_indirect: var_from_fixture_indirect
示例 2:通过 request 获取参数值
  • 通过 request 参数获取原始的参数化值
  • 使用 request.node.callspec.params 访问参数字典
python 复制代码
@pytest.mark.parametrize("fixture_indirect", [110, 120], indirect=True)
def test_fixture_indirect_request(fixture_indirect, request):
    print(f"Case fixture_indirect: {fixture_indirect}")
    my_test_param = request.node.callspec.params['fixture_indirect']
    print(f"Case request.param: {my_test_param}")

"""
除了基本功能外,还能获取原始参数:
- fixture 的返回值: var_from_fixture_indirect
- 原始参数值: 110/120
"""
复制代码
fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect_request[110]>>
fixture_indirect, request.param: 110
PASSED  [ 50%]
Case fixture_indirect: var_from_fixture_indirect
Case request.param: 110

fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect_request[120]>>
fixture_indirect, request.param: 120
PASSED  [100%]
Case fixture_indirect: var_from_fixture_indirect
Case request.param: 120
示例 3:多参数组合测试
  • 如何组合多个参数化装饰器
  • 直接参数化和间接参数化的混合使用
python 复制代码
@pytest.mark.parametrize("fixture_indirect", [111, 222], indirect=True)
@pytest.mark.parametrize("test_param", ['a', 'b'])
def test_fixture_param(fixture_indirect, test_param):
    print(f"fixture_indirect: {fixture_indirect}")
    print(f"test_param: {test_param}")

"""
会生成 4 个测试用例组合:
(111, 'a')
(111, 'b')
(222, 'a')
(222, 'b')
"""
复制代码
fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_param[a-111]>>
fixture_indirect, request.param: 111
PASSED           [ 25%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: a
PASSED           [ 50%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: b

fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_param[a-222]>>
fixture_indirect, request.param: 222
PASSED           [ 75%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: a
PASSED           [100%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: b
示例 4:部分间接参数化
  • 如何在一个参数化中同时使用直接和间接参数
  • 使用 indirect 列表指定哪些参数是间接的
python 复制代码
@pytest.mark.parametrize("fixture_indirect, my_test_param",
                         [(111, 'a'), (222, 'b')],
                         indirect=['fixture_indirect'])
def test_fixture_indirect_param_partial(fixture_indirect, my_test_param):
    print(f"Case fixture_indirect: {fixture_indirect}")
    print(f"Case test_param: {my_test_param}")

"""
会生成 2 个测试用例:
(111, 'a')
(222, 'b')
"""
复制代码
fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect_param_partial[111-a]>>
fixture_indirect, request.param: 111
PASSED [ 50%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: a

fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect_param_partial[222-b]>>
fixture_indirect, request.param: 222
PASSED [100%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: b

4. 最佳实践

  1. 选择合适的参数化方式

    • 简单参数使用直接参数化
    • 需要预处理或者复杂设置的参数使用间接参数化
  2. 合理使用 scope

    • 对于耗时的 fixture,使用更大的 scope(如 module)可以提高测试效率
    • 注意 scope 对测试隔离的影响
  3. 参数化组织建议

    • 相关的参数组合放在一起
    • 使用有意义的参数名
    • 考虑测试的可读性和维护性

5. 总结

Pytest 的参数化和 fixture 功能为我们提供了强大而灵活的测试工具:

  1. 灵活性:可以根据需要选择直接或间接参数化
  2. 可复用性:fixture 机制支持测试代码的重用
  3. 可维护性:通过合理组织参数和 fixture,使测试代码更易维护
  4. 效率:支持多种方式组合参数,提高测试效率

掌握这些高级用法,可以帮助我们写出更好的测试代码,提高测试效率和代码质量。

参考资料

相关推荐
头疼的程序员16 小时前
allure生成测试报告(搭配Pytest、allure-pytest)
测试工具·pytest
文人sec1 天前
接口自动化测试设计思路--设计实战
python·https·单元测试·自动化·pytest
测试开发Kevin3 天前
从投入产出、效率、上手难易度等角度综合对比 pytest 和 unittest 框架
python·pytest
测试开发Kevin5 天前
以pytest_addoption 为例,讲解pytest框架中钩子函数的应用
python·pytest
川石教育11 天前
Pytest中的fixture装饰器详解
python自动化测试·pytest·pytest自动化测试框架·pytest测试框架·pytest单元测试框架
春风又。11 天前
接口自动化——参数化
python·测试工具·自动化·pytest
XTY0013 天前
mac电脑pytest生成测试报告
pytest
程序员的世界你不懂13 天前
pytest-前后置及fixture运用
pytest
天才测试猿15 天前
基于Pytest接口自动化的requests模块项目实战以及接口关联方法详解
自动化测试·软件测试·python·测试工具·单元测试·测试用例·pytest
HtwHUAT15 天前
五、UI自动化测试05--PyTest框架
经验分享·python·ui·pytest