AIGC标识 pytest 入门指南:Python 自动化测试的标配工具

写代码不写测试,改一处崩一片。Python 标准库有 unittest,但 pytest 以更少的样板代码、更聪明的断言、丰富的插件生态成为社区主流。本文带你从第一个测试用例到 fixtures 实战。

一、环境准备

pip install pytest
# 验证
pytest --version

要求 Python 3.8+。无需额外配置,约定大于配置。

二、最小可运行示例

假设有业务函数 calc.py:

# calc.py
def add(a, b):
    return a + b

写测试 test_calc.py(文件名以 test_ 开头,函数以 test_ 开头):

# test_calc.py
from calc import add

def test_add_int():
    assert add(1, 2) == 3

def test_add_str():
    assert add("a", "b") == "ab"

运行:pytest,pytest 自动发现并执行所有 test_* 用例,绿色 PASSED 即通过。

三、核心概念

  • 自动发现:默认找 test_*.py 或 *_test.py,函数/类以 test_ 开头。
  • 断言即测试:直接用 Python assert,失败自动展示变量值,无需 self.assertEqual。
  • Fixture:用 @pytest.fixture 准备测试前置数据/资源,可复用、可依赖。

四、进阶用法:fixture 与参数化

用 fixture 共享数据库连接,用参数化一次测多组输入:

import pytest

@pytest.fixture
def sample_data():
    return [1, 2, 3, 4]

def test_sum(sample_data):
    assert sum(sample_data) == 10

@pytest.mark.parametrize("a,b,expect", [
    (1, 1, 2), (0, 0, 0), (-1, 1, 0),
])
def test_add(a, b, expect):
    assert add(a, b) == expect

参数化让一个函数跑出多组用例,报告清晰。

五、实战场景:测试带异常的代码

验证函数该抛异常时抛异常:

import pytest

def divide(a, b):
    if b == 0:
        raise ValueError("b 不能为 0")
    return a / b

def test_divide_zero():
    with pytest.raises(ValueError):
        divide(1, 0)

pytest.raises 上下文管理器断言异常类型,是测试防御性代码的利器。

六、常见坑 / 报错

1. collected 0 items
pytest 没找到用例。检查文件名/函数名是否以 test_ 开头,或在正确目录运行。

2. fixture 'xxx' not found
被引用的 fixture 未定义或未在同文件/conftest.py 中。把公共 fixture 放到 conftest.py 可全局共享。

3. 断言失败但看不出原因
用 assert a == b 而非自定义比较,pytest 会打印两侧实际值。复杂对象可用 pytest.approx 做浮点近似:assert val == pytest.approx(0.1)。

七、总结与下一步

pytest 用极简写法撬动专业测试:自动发现、智能断言、fixture 复用、参数化覆盖。下一步建议:

  • 加 pytest-cov 看测试覆盖率;
  • 用 pytest-mock 隔离外部依赖;
  • 接入 CI(GitHub Actions)让每次提交自动跑测试。

写好 pytest,你的 Python 代码才真正“稳得住”。

posted @ 2026-09-24 18:50  小小张说故事  阅读(3)  评论(0)    收藏  举报