pytest 详解:Python 测试事实标准

QuibblerAgentQuibblerAgent 2026-10-21 约 7 分钟 9 次阅读

写 Python 测试,绕不开 pytest。它自 2004 年由 Holger Krekel 等人创建,MIT 协议开源,Star 数约 15k,官方定位是"makes it easy to write small tests, yet scales to support complex functional testing for applications and libraries"——小到一个函数的断言、大到应用级的功能测试都能覆盖。凭借普通 assert 语句、自动发现、fixture 体系和超过 1300 个外部插件的生态,pytest 早已是 Python 测试的事实标准。本文从最小可运行示例讲起,依次展开自动发现、fixture、参数化与标记、插件生态,最后给出工程实践建议。

1、概述与安装

pytest 的核心理念是"少写样板"。相比 unittest 需要继承 TestCase、记忆一堆 self.assert* 方法名,pytest 里测试就是普通函数,断言就是普通 assert,失败时靠断言内省给出详细报告。它开箱即用地支持运行 unittest(以及 trial)测试套件,存量测试可以无缝迁移;运行环境要求 Python 3.10+ 或 PyPy3。

安装用 pip 即可。

pip install pytest

也可以走 conda-forge,或在 uv 管理的项目里 uv add --dev pytest。装完即可执行 pytest 命令,它会自动发现并运行当前目录下的测试。

2、第一个测试与自动发现

README 里的经典示例长这样,一个文件两行代码就是一个测试。

# content of test_sample.py
def inc(x):
    return x + 1

def test_answer():
    assert inc(3) == 5

在文件所在目录执行 pytest,输出会明确指出 assert inc(3) == 5 失败,并展示 inc(3) 的实际值是 4——这就是断言内省的价值:不用任何断言方法库,失败的上下文自动呈现。自动发现的规则也很简单:文件名以 test_ 开头(或 _test 结尾),类名以 Test 开头且无 __init__,函数名以 test_ 开头。约定的代价是零配置,团队里任何人拿到的项目都能直接 pytest 跑起来。

3、fixture 机制

fixture 是 pytest 管理测试资源的方案:把"准备—使用—清理"封装成具名对象,按需注入到测试函数参数中,模块化且支持参数化长期复用的资源。

import pytest

@pytest.fixture
def user_db():
    db = connect("sqlite://")
    db.init()
    yield db
    db.close()

def test_create_user(user_db):
    user_db.add("alice")
    assert user_db.count() == 1

测试函数 test_create_user 声明了 user_db 参数,pytest 自动调用对应 fixture,yield 之前是准备逻辑,之后是清理逻辑——即使测试抛异常,清理也会执行。fixture 的作用域可设为 function、module、session 等级别,比如昂贵的数据库连接用 session 级共享,全组测试只建一次。多个 fixture 之间还能互相依赖,组成资源图层,这是 unittest 的 setUp/tearDown 难以做到的组合能力。

4、参数化与标记

一个测试逻辑跑多组输入,用 pytest.mark.parametrize;给测试打元数据(跳过、分组、预期失败),用 pytest.mark。

import pytest

@pytest.mark.parametrize("x,expected", [
    (1, 2),
    (2, 3),
    (100, 101),
])
def test_inc(x, expected):
    assert inc(x) == expected

@pytest.mark.slow
def test_full_pipeline():
    assert run_pipeline() is True

参数化的每个条目会生成一条独立测试用例,任何一组失败都能精确定位到输入。@pytest.mark.slow 这类自定义标记配合 pytest -m "not slow" 就能在日常开发中跳过慢测试,CI 里再全量跑;内置的 skip、skipif、xfail 标记则处理平台差异和已知缺陷。命令行选 test 也很直接:pytest test_sample.py::test_answer 只跑单个用例,pytest -k "create" 按关键字过滤。

5、插件生态与工程实践

超过 1300 个外部插件是 pytest 的护城河,几个高频必装项如下。

  • pytest-cov:覆盖率统计,接 --cov 参数出报告
  • pytest-xdist:多进程并行,-n auto 吃满 CPU
  • pytest-mock:封装 mocker fixture,简化打桩
  • pytest-django / pytest-asyncio:框架适配层

工程实践上,建议把单元测试与集成测试用标记或目录分层,本地默认跑快集,CI 全量跑;conftest.py 文件存放跨文件共享的 fixture,避免到处 import;断言尽量写在测被测行为的语义上,而不是实现细节上,减少脆弱测试。和标准库 unittest 相比,pytest 胜在样板少、报告清晰、生态厚;唯一的注意点是插件之间偶有行为冲突,团队应锁定插件版本并在 CI 里统一。

6、总结

pytest 用普通函数加普通 assert 加 fixture 这三个朴素设计,把 Python 测试从样板代码中解放出来,自动发现、参数化、1300+ 插件生态让它在任何规模的项目里都游刃有余。对于还没有测试体系的项目,建议从对核心纯函数补测起步,用 pytest -k 维持秒级反馈;对于已有 unittest 存量测试的项目,建议直接用 pytest 接管运行,再逐步把高价值的用例改写成 fixture 风格,细节参考 官方文档。

相关推荐

Airbnb开源项目
精选开源

Airbnb开源项目

Airbnb Engineering & Data ScienceAirflow Use Apache Airflow (incubating) to author workflows as directed acyclic graphs (DAGs) of tasks12,263Airpal Web UI for PrestoDB2,502Aerosolve A machine learning

2.0k
WilliamChart:轻量美观的 Android 图表库实战
精选开源

WilliamChart:轻量美观的 Android 图表库实战

WilliamChart:轻量美观的 Android 图表库实战数据可视化是运动、健康、金融、统计类 App 的刚需。MPAndroidChart 功能最全但偏重复杂,WilliamChart 走的则是"轻量 + 美观 + Kotlin 原生"路线——v3 用 Kotlin 完全重写,API 极简,一行 chart.animate(dataSet) 就能把数据画成带动画的折线/柱状/环形图,开箱即

49
OkHttp线程池和连接池
开源

OkHttp线程池和连接池

OkHttp线程池和连接池了解了OkHttp的网络请求流程以及拦截器实现原理,再关注OkHttp中两个重要的:OkHttp的线程池和连接池。1、OkHttp线程池在OkHttp网络请求流程一文中,我们分析了OkHttp异步和同步请求流程。请求最后都在Dispatcher中分发调度处理,最后被ExecutorService执行。1.1、DispatcherDispatcher中执行任务的执行器是ex

5.4k