pytest-check 是补充而非替代 assert 的断言库:它允许单个测试内执行多个断言并延迟汇总失败,而 assert 一失败即中断;所有检查基于原生布尔表达式,需显式调用 check.equal() 等函数。

pytest-check 是什么,和 assert 有什么区别
pytest-check 不是替代 assert,而是补充它:默认的 assert 一失败就中断测试,而 pytest-check 允许你在一个测试函数里执行多个断言,全部跑完再汇总失败项。适合校验一组关联字段(比如 API 返回的 JSON 中多个 key 是否都符合预期),或 UI 自动化中检查多个元素状态。
常见错误现象是:写了 5 个 assert,第 2 个就失败了,后面 3 个根本没执行,你不知道它们是否也错——这在调试时很被动。
- 它不改变 pytest 的生命周期,只是把断言“延迟上报”
- 所有检查仍基于 Python 原生布尔表达式,写法几乎一样
- 必须显式调用
check.equal(a, b)这类函数,不能直接写check(a == b)
安装与基础用法:怎么让 check 函数可用
先装包:
pip install pytest-check
然后在测试文件顶部导入:from pytest_check import check
注意:不是 import pytest_check,也不是 from pytest_check import *——后者会污染命名空间,且部分 IDE 无法正确识别函数签名。
常用检查函数包括:
check.equal(actual, expected)check.is_in(item, container)check.is_true(condition)check.greater(actual, expected)
所有函数都接受一个可选参数 msg,用于自定义失败提示,比如 check.equal(len(items), 3, msg="应返回恰好3条记录")
多重断言失败后怎么定位具体哪条错了
pytest-check 默认会在测试结束时抛出一个 CheckFailure 异常,消息体里列出所有失败项,格式清晰:
Failed Checks (2):
check.equal(1, 2) → AssertionError: 1 != 2
check.is_in('x', ['a', 'b']) → AssertionError: 'x' not in ['a', 'b']
关键点:
- 每条失败都保留原始调用栈的行号(依赖 pytest 的异常捕获机制)
- 如果你在 CI 环境跑,这个汇总信息会完整输出到日志,不用反复 rerun
- 不支持单条断言单独标记 skip 或 xfail;想跳过某条检查,得用条件包裹,比如
if should_check_email: check.is_not_none(user.email)
和 pytest 的 fixture、parametrize 一起用要注意什么
可以无缝配合,但有两个易踩坑点:
-
check函数本身不触发 pytest 的 assertion rewriting,所以像check(a is not None)这种写法不会被重写为更友好的报错信息;推荐改用check.is_not_none(a) - 在
@pytest.mark.parametrize场景下,每组参数是独立测试用例,check的汇总只作用于当前用例内,这点和直觉一致,但新手有时误以为能跨用例累积
另外,不要在 fixture teardown 里用 check——fixture 报错会被 pytest 当作 setup 失败处理,而 check 的延迟机制在此处失效,可能静默吞掉失败。
真正容易被忽略的是:如果你在同一个测试函数里混用 assert 和 check,一旦 assert 先失败,check 就没机会执行了。想保多重校验,整段逻辑得统一用 check.*。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











