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 代码才真正“稳得住”。

浙公网安备 33010602011771号