pytest

Framework

pytest-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)

Troubleshooting
How 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.

GitHub Issue #15190
Troubleshooting
How 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.

GitHub Issue #12839
Troubleshooting
How 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: ")

GitHub Issue #12175
Troubleshooting
Why 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.

GitHub Issue #15080
Troubleshooting
Why 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.

GitHub Issue #15081