Pytest 单元测试入门指南

Pytest 是 Python 常用测试框架。本文从安装讲起:编写与运行测试、测试设计原则、用例过滤、参数化、异常断言、fixture 与插件生态,一篇上手。

最佳实践
测试检测与质量验证插画

本文依据官方文档整理,未执行运行验证或性能基准。代码片段展示局部用法,业务函数、数据和环境需按项目补齐;版本与配置以所引文档为准。

直接回答:Pytest 凭借直观的断言语法(直接写 assert)、强大的 fixture 机制和庞大的插件生态,成为 Python 测试中常见的选择——写好普通函数、用 assert 断言,剩下的交给 pytest。

为什么是 Pytest

相比标准库 unittest 的类继承套路,pytest 的哲学是"少仪式":测试就是普通函数,断言就是普通 assert(失败时自动展开详细的值对比),依赖注入交给 fixture,批量场景交给参数化。可减少部分测试组织样板,具体差异取决于项目。

安装与第一条测试

pip install pytest

被测代码 calc.py:

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

测试 test_calc.py:

from calc import divide

def test_divide():
    assert divide(10, 2) == 5

pytest 会自动发现 test_*.py 文件里 test_ 开头的函数并执行。

运行方式

pytest                    # 全量
pytest test_calc.py       # 指定文件
pytest -v                 # 详细输出
pytest -x                 # 首个失败即停
pytest --lf               # 只跑上次失败的

设计好测试的三条原则

  1. 一条用例一个关注点:失败时标题即结论;
  2. AAA 结构:Arrange(准备)→ Act(执行)→ Assert(断言),段落分明;
  3. 边界优先:正常值之外,空值、零、极大值、非法输入才是 bug 高发区。

过滤测试

pytest -k "divide"            # 按名字模糊匹配
pytest -m slow                # 按标记运行(需 @pytest.mark.slow)
pytest test_calc.py::test_divide   # 精确到单条

参数化:一组输入一份代码

import pytest

@pytest.mark.parametrize("a,b,want", [
    (10, 2, 5),
    (9, 3, 3),
    (1, 4, 0.25),
])
def test_divide(a, b, want):
    assert divide(a, b) == want

用例多了还可以把参数抽成数据类,让每组场景带名字和语义,报告更易读。

断言异常

def test_divide_by_zero():
    with pytest.raises(ValueError, match="除数不能为零"):
        divide(1, 0)

pytest.raises 同时验证异常类型与消息,比 try/except 断言优雅得多。

fixture 快速上手

@pytest.fixture
def client():
    return TestClient(app)

def test_health(client):
    assert client.get("/health").status_code == 200

把共享 fixture 放进对应目录的 conftest.py,可供该目录及子目录测试使用(详见 fixtures 专题篇)。

插件生态

  • pytest-cov:覆盖率;
  • pytest-xdist:多进程并行;
  • pytest-asyncio:异步测试;
  • pytest-mock:Mock 语法糖;
  • pytest-rerunfailures:失败重跑。

插件通常还需要版本匹配、标记或配置;例如pytest-asyncio的使用方式取决于所选模式,这是 pytest 长盛不衰的护城河。

常见问题(FAQ)

Q:pytest 和 unittest 怎么选?
A:新项目直接 pytest:写法更简洁、生态更繁荣。存量 unittest 代码不用重写——pytest 能直接收集运行 unittest 用例,可以渐进迁移。

Q:assert 被 Python 优化模式(-O)去掉怎么办?
A:默认重写的测试模块断言可保留,但普通被导入模块、关闭重写的模块仍可能受 -O 影响。不要以 -O 运行套件来假定所有断言可靠;生产业务校验应显式抛异常。

Q:测试变慢怎么排查?
A:先 -v --durations=10 找出最慢的十条;重资源改长作用域 fixture;最后上 pytest-xdist 并行。

官方参考

资料核对日期:2026-09-29。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台