项目简介
pytest 是一个成熟的全功能 Python 测试工具,支持 fixture 参数化、丰富的插件架构和自动测试发现。提供详细的断言失败信息,方便调试。
README 预览
.. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg\n :target: https://docs.pytest.org/en/stable/\n :align: center\n :height: 200\n :alt: pytest\n\n\n------\n\n.. image:: https://img.shields.io/pypi/v/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://img.shields.io/conda/vn/conda-forge/pytest.svg\n :target: https://anaconda.org/conda-forge/pytest\n\n.. image:: https://img.shields.io/pypi/pyversions/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/main/graph/badge.svg\n :target: https://codecov.io/gh/pytest-dev/pytest\n :alt: Code coverage Status\n\n.. image:: https://github.com/pytest-dev/pytest/actions/workflows/test.yml/badge.svg\n :target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Atest\n\n.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg\n :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main\n :alt: pre-commit.ci status\n\n.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg\n :target: https://www.codetriage.com/pytest-dev/pytest\n\n.. image:: https://readthedocs.org/projects/pytest/badge/?version=latest\n :target: https://pytest.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n.. image:: https://img.shields.io/badge/Discord-pytest--dev-blue\n :target: https://discord.com/invite/pytest-dev\n :alt: Discord\n\n.. image:: https://img.shields.io/badge/Libera%20chat-%23pytest-orange\n :target: https://web.libera.chat/#pytest\n :alt: Libera chat\n\n\nThe ``pytest`` framework makes it easy to write small tests, yet\nscales to support complex functional testing for applications and libraries.\n\nAn example of a simple test:\n\n.. code-block:: python\n\n # content of test_sample.py\n def inc(x):\n return x + 1\n\n\n def test_answer():\n assert inc(3) == 5
常见问题 (5)
故障排除如何修复 Sphinx 文档构建因 "py:class reference target not found: pluggy._compat.DistFacade" 警告而失败的问题?
此错误发生在使用 Pluggy 1.7.0 构建文档时(例如为 pytest 运行 tox -e docs),因为其 PluginManager.list_plugin_distinfo 的文档字符串引用了私有的、未文档化的类 pluggy._compat.DistFacade,而 -W 会将警告转变为失败。修复方法:在你的 Sphinx conf.py 中将该私有类添加到 nitpick_ignore:
nitpick_ignore = [
# ... 现有条目 ...
("py:class", "pluggy._compat.DistFacade"),
]
这样可以在不锁定或降级 Pluggy 的情况下,对所有其他目标保持严格的引用检查。注意:降级到 Pluggy 1.6.0 并不是有效的变通方案,因为它会触发其他私有 Pluggy 类型引用的警告。
故障排除如何修复在比较嵌套序列时出现的 pytest.approx() AttributeError: 'tuple' object has no attribute 'expected' 错误?
pytest.approx() 不支持嵌套数据结构,例如元组列表(如 pytest.approx([(2.0, 2.0)]))。在 pytest <= 9.1.1 中,这会在断言报告期间产生令人困惑的 AttributeError: 'tuple' object has no attribute 'expected'。
解决方法:
1. 在比较前将结构展平:assert [x for t in sut() for x in t] == pytest.approx([2.0, 2.0])
2. 逐个比较元素:result = sut(); assert result[0] == pytest.approx((2.0, 2.0))(单个扁平的数字元组/列表是支持的)
3. 对于数值二维数据,使用 numpy 数组,approx 可以处理。
升级到 pytest 9.2+(来自 PR #14934 的修复)并不会让嵌套结构可用,但会将晦涩难懂的 AttributeError 替换为清晰的错误信息:TypeError: pytest.approx() does not support nested data structures。你仍然必须按照上述方法重构比较。
故障排除如何修复 pytest exconly(tryshort=True) 无法移除 'AssertionError: ' 的问题?
这是 pytest 8.0.2 及相关版本中的一个 bug:ExceptionInfo.for_later() 在异常被捕获之前就创建了 ExceptionInfo,并且从未填充其断言 striptext,因此 exconly(tryshort=True) 会保留 AssertionError: 前缀。
直接使用异常值:
with pytest.raises(AssertionError) as exc_info:
raise AssertionError("message")
message = str(exc_info.value)
assert message == "message"
如果需要保留 exconly() 的行为,可以从捕获的异常重新构造 ExceptionInfo:
from pytest import ExceptionInfo
message = ExceptionInfo.from_exception(
exc_info.value
).exconly(tryshort=True)
一个适用于 Python 3.9+ 的字符串解决方法是:
message = str(exc_info.value).removeprefix("AssertionError: ")故障排除为什么 pytest 收集了一个测试类,却在它继承 ABCMeta 抽象方法时报告没有测试?
在 pytest 8.3+ 中,抽象测试类会在收集期间被跳过。你的 TestFoo 类仍然是抽象的,因为它没有实现继承而来的 test_foo 方法,所以 pytest 会静默地从中收集不到任何内容。
验证未实现的抽象方法:
python -c "import your_test_module; print(your_test_module.TestFoo.__abstractmethods__)"
这应该会打印 {'test_foo'}。通过在具体测试类中实现每个抽象方法来修复此问题:
class TestFoo(AbstractTestFoo):
def test_foo(self):
assert True
然后再次运行 pytest。如果该类是有意设计为抽象的,或者不应被收集,请将其重命名为不以 Test 开头的名称,或者设置 __test__ = False。关于被静默跳过的抽象类的 pytest 警告,此前一直在 issue #13546 和草案 PR #15082 中跟踪。
故障排除为什么当我的测试类继承了抽象方法时,pytest 会报告 'collected 0 items'?
TestFoo 仍然是抽象类,因为它继承了 test_foo 却没有实现它。Pytest 在收集阶段会跳过抽象类,因此不会收集到任何测试实例或测试方法。请在具体子类中实现该抽象方法:
class TestFoo(AbstractTestFoo):
def test_foo(self):
assert True # your test
使用以下命令验证收集情况:
pytest --collect-only
现在它应该会列出 TestFoo::test_foo。在 pytest 9.1.1 中,这种情况会被静默跳过;在收集阶段报错或发出警告仅是一项提议中的变更。