写点什么

Pytest 参数化与基本装饰器用法

  • 2024-11-26
    北京
  • 本文字数:2287 字

    阅读完需:约 8 分钟

全面解析软件测试开发:人工智能测试、自动化测试、性能测试、测试左移、测试右移到DevOps如何驱动持续交付 

Pytest 是 Python 社区广泛使用的测试框架,提供了灵活的功能来提升测试覆盖率和代码质量。本文将详细介绍 Pytest 的 参数化 和 基本装饰器用法,帮助你在编写测试用例时更加高效和灵活。


一、Pytest 参数化(Parametrize)

1. 什么是参数化?

参数化是指在一个测试用例中使用多组不同的数据,避免重复编写类似的测试代码,从而提升测试效率。

2. 参数化的基本语法

Pytest 提供了 @pytest.mark.parametrize 装饰器来实现参数化测试。

语法

@pytest.mark.parametrize("参数名1, 参数名2, ...", [(值1, 值2, ...), ...])def 测试函数(参数名1, 参数名2, ...):    # 测试逻辑
复制代码

3. 单参数的参数化

测试单一参数的多种情况:

import pytest
@pytest.mark.parametrize("number", [1, 2, 3, 4])def test_is_positive(number): assert number > 0
复制代码

执行结果:

test_example.py::test_is_positive[1] PASSEDtest_example.py::test_is_positive[2] PASSEDtest_example.py::test_is_positive[3] PASSEDtest_example.py::test_is_positive[4] PASSED
复制代码

4. 多参数的参数化

当测试函数需要多个参数时,可以提供参数组合:

import pytest
@pytest.mark.parametrize("a, b, expected", [ (1, 2, 3), (2, 3, 5), (3, 5, 8),])def test_addition(a, b, expected): assert a + b == expected
复制代码

执行结果:

test_example.py::test_addition[1-2-3] PASSEDtest_example.py::test_addition[2-3-5] PASSEDtest_example.py::test_addition[3-5-8] PASSED
复制代码

5. 参数组合:笛卡尔积

通过 @pytest.mark.parametrize 的多重装饰实现笛卡尔积的参数组合:

import pytest
@pytest.mark.parametrize("a", [1, 2])@pytest.mark.parametrize("b", [3, 4])def test_combinations(a, b): print(f"Testing combination: {a}, {b}") assert a + b in [4, 5, 6]
复制代码

生成的组合:

  • (1, 3)

  • (1, 4)

  • (2, 3)

  • (2, 4)

6. 参数化数据来源:读取外部数据

从 JSON 文件读取

import pytestimport json
def load_test_data(): with open("test_data.json", "r") as file: return json.load(file)
@pytest.mark.parametrize("a, b, expected", load_test_data())def test_from_json(a, b, expected): assert a + b == expected
复制代码

从 CSV 文件读取

import pytestimport csv
def load_csv(file_path): with open(file_path, "r") as file: return [tuple(row) for row in csv.reader(file)]
@pytest.mark.parametrize("a, b, expected", load_csv("test_data.csv"))def test_from_csv(a, b, expected): assert int(a) + int(b) == int(expected)
复制代码

二、Pytest 基本装饰器用法

Pytest 提供了多种装饰器,帮助控制测试的执行行为,例如 跳过测试预期失败条件跳过 和 自定义标记

1. 跳过测试

直接跳过

如果某些测试暂时不需要执行,可以使用 @pytest.mark.skip

import pytest
@pytest.mark.skip(reason="Feature not implemented")def test_not_ready(): assert 1 + 1 == 2
复制代码

条件跳过

根据条件决定是否跳过测试:

import pytestimport sys
@pytest.mark.skipif(sys.version_info < (3, 8), reason="Requires Python 3.8+")def test_python_version(): assert 1 + 1 == 2
复制代码

2. 标记预期失败

如果某个功能尚未完善,测试会失败,但我们希望忽略失败结果,可以使用 @pytest.mark.xfail

import pytest
@pytest.mark.xfail(reason="Known bug")def test_known_bug(): assert 1 + 1 == 3
复制代码

运行结果会显示 XFAIL

3. 自定义标记

标记是 Pytest 用于分组和筛选测试用例的强大工具。使用 @pytest.mark 为测试用例添加自定义标记:

import pytest
@pytest.mark.smokedef test_quick_check(): assert 1 + 1 == 2
@pytest.mark.regressiondef test_full_check(): assert 2 * 3 == 6
复制代码

运行特定分组测试用例:

pytest -m smoke
复制代码

4. 自定义装饰器与作用范围

Fixture 的作用范围

  • function(默认):每个测试函数调用一次。

  • module:在模块范围内共享。

  • class:在类范围内共享。

  • session:在会话范围内共享。

示例:

import pytest
@pytest.fixture(scope="module")def setup_module(): print("Setting up module") return "Resource"
def test_resource_1(setup_module): assert setup_module == "Resource"
def test_resource_2(setup_module): assert setup_module == "Resource"
复制代码

5. 参数化与装饰器结合

参数化可以与其他装饰器组合使用,例如条件跳过:

import pytest
@pytest.mark.parametrize("input, expected", [(1, 2), (3, 4)])@pytest.mark.skipif(condition=True, reason="Skipped for demonstration")def test_skip_with_parametrize(input, expected): assert input + 1 == expected
复制代码

三、最佳实践总结

  1. 充分利用参数化


  • 避免硬编码,提升测试覆盖率。

  • 使用外部文件存储测试数据,增强数据管理能力。


  1. 灵活使用装饰器


  • 跳过和标记功能可以帮助测试流程更高效。

  • 使用条件跳过和预期失败,优化测试策略。


  1. 与 CI/CD 集成


  • 结合 pytest.mark 对测试分组,在不同场景中灵活选择运行测试用例。


  1. 维护清晰的日志和报告


  • 使用 pytest-html 或 pytest-cov 生成详细的报告,帮助分析测试结果。

Pytest 的参数化和装饰器功能为自动化测试提供了强大的灵活性和可扩展性。通过合理使用这些功能,可以显著提升测试用例的质量和可维护性。如果你有更多关于 Pytest 的问题,欢迎一起探讨!


用户头像

社区:ceshiren.com 微信:ceshiren2023 2022-08-29 加入

微信公众号:霍格沃兹测试开发 提供性能测试、自动化测试、测试开发等资料、实事更新一线互联网大厂测试岗位内推需求,共享测试行业动态及资讯,更可零距离接触众多业内大佬

评论

发布
暂无评论
Pytest 参数化与基本装饰器用法_测试_测吧(北京)科技有限公司_InfoQ写作社区