pytest
Frameworkpytest-dev/pytest
Python testing framework for simple to complex functional testing.
Overview
pytest is a mature full-featured Python testing tool that helps write better programs. It supports fixture parametrization, a rich plugin architecture, and auto-discovery of tests. Detailed info on failing assertions makes debugging easy.
README Preview
.. 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
FAQ (5)
TroubleshootingHow to fix Sphinx docs build failing with "py:class reference target not found: pluggy._compat.DistFacade" warning?
This error occurs when building docs (e.g., tox -e docs for pytest) with Pluggy 1.7.0, because its PluginManager.list_plugin_distinfo docstring references the private, undocumented class pluggy._compat.DistFacade, and -W turns the warning into a failure. Fix: add the private class to nitpick_ignore in your Sphinx conf.py:
nitpick_ignore = [
# ... existing entries ...
("py:class", "pluggy._compat.DistFacade"),
]
This keeps strict reference checking for all other targets without pinning or downgrading Pluggy. Note: downgrading to Pluggy 1.6.0 is not a valid workaround, as it triggers other private Pluggy-type reference warnings.
TroubleshootingHow to fix pytest.approx() AttributeError: 'tuple' object has no attribute 'expected' when comparing nested sequences?
pytest.approx() does not support nested data structures such as a list of tuples (e.g., pytest.approx([(2.0, 2.0)])). On pytest <= 9.1.1 this produces a confusing AttributeError: 'tuple' object has no attribute 'expected' during assertion reporting.
Workarounds:
1. Flatten the structure before comparing: assert [x for t in sut() for x in t] == pytest.approx([2.0, 2.0])
2. Compare elements individually: result = sut(); assert result[0] == pytest.approx((2.0, 2.0)) (a single flat tuple/list of numbers is supported)
3. For numeric 2D data, use numpy arrays, which approx handles.
Upgrading to pytest 9.2+ (fix from PR #14934) won't make nested structures work, but replaces the cryptic AttributeError with a clear error: TypeError: pytest.approx() does not support nested data structures. You must still restructure the comparison as shown above.
TroubleshootingHow to fix pytest exconly(tryshort=True) not removing 'AssertionError: '?
This is a bug in pytest 8.0.2 and related versions: ExceptionInfo.for_later() creates the ExceptionInfo before the exception is captured and never populates its assertion striptext, so exconly(tryshort=True) keeps the AssertionError: prefix.
Use the exception value directly:
with pytest.raises(AssertionError) as exc_info:
raise AssertionError("message")
message = str(exc_info.value)
assert message == "message"
If you need to preserve exconly() behavior, reconstruct the ExceptionInfo from the captured exception:
from pytest import ExceptionInfo
message = ExceptionInfo.from_exception(
exc_info.value
).exconly(tryshort=True)
A Python 3.9+ string workaround is:
message = str(exc_info.value).removeprefix("AssertionError: ")TroubleshootingWhy does pytest collect a test class but report no tests when it inherits an ABCMeta abstract method?
In pytest 8.3+, abstract test classes are skipped during collection. Your TestFoo class remains abstract because it does not implement the inherited test_foo method, so pytest silently collects nothing from it.
Verify the unimplemented abstract methods:
python -c "import your_test_module; print(your_test_module.TestFoo.__abstractmethods__)"
This should print {'test_foo'}. Fix it by implementing every abstract method in the concrete test class:
class TestFoo(AbstractTestFoo):
def test_foo(self):
assert True
Then run pytest again. If the class is intentionally abstract or should not be collected, rename it so it does not start with Test, or set __test__ = False. A pytest warning for silently skipped abstract classes was being tracked in issue #13546 and draft PR #15082.
TroubleshootingWhy does pytest report 'collected 0 items' when my test class inherits an abstract method?
TestFoo is still abstract because it inherits test_foo without implementing it. Pytest skips abstract classes during collection, so no test instance or test method is collected. Implement the abstract method in the concrete subclass:
class TestFoo(AbstractTestFoo):
def test_foo(self):
assert True # your test
Verify collection with:
pytest --collect-only
It should now list TestFoo::test_foo. In pytest 9.1.1, this condition is skipped silently; failing or warning during collection was only a proposed change.