pytest
Run automated software tests
TLDR
Run tests from specific files
Run tests with names matching a specific [k]eyword expression
Exit as soon as a test fails or encounters an error
Run tests matching or excluding markers
Run until a test failure, continuing from the last failing test
Run tests without capturing output
SYNOPSIS
pytest [options] [files_or_directories_or_nodeids]
PARAMETERS
--verbose, -v
Increase verbosity.
--quiet, -q
Decrease verbosity.
--capture=no, -s
Disable capturing of stdout/stderr during test execution.
--exitfirst, -x
Exit instantly on first error or failed test.
--last-failed, --lf
Rerun only the tests that failed in the previous run.
--failed-first, --ff
Run previously failed tests first, then the rest.
--durations=N
Show the N slowest test durations (or 0 for all).
-k EXPRESSION
Only run tests whose names match the given substring expression. Example: -k "MyClass and not method".
-m MARKEXPR
Only run tests matching the given marker expression. Example: -m "slow or webtest".
--strict-markers
Enforce that markers used are registered in pytest.ini or pyproject.toml.
--collect-only
Dry run: collect tests without executing them.
-r CHARS
Show extra test summary info for failed, passed, skipped, xfailed, xpassed tests. Example: -r sfE.
--numprocesses=N, -n N
Distribute tests across N processes (requires pytest-xdist plugin).
DESCRIPTION
pytest is a powerful and popular Python testing framework designed for writing simple, readable, and scalable tests. It emphasizes developer productivity by providing a low-boilerplate approach to test writing compared to Python's built-in unittest module. Key features include automatic test discovery, a rich plugin architecture, a flexible fixture system for managing test setup and teardown, and assert rewriting for more informative assertion failures without special syntax.
pytest tests are typically written as simple Python functions that start with test_ within files that start or end with test_. It supports parametrizing tests, allowing a single test function to be run with various sets of inputs, reducing code duplication. Its extensive plugin ecosystem further enhances its capabilities, offering integrations for coverage reporting, parallel test execution (pytest-xdist), mock objects, and more. Used widely in industry and open-source projects, pytest facilitates writing clear, maintainable, and high-quality test suites for applications of all sizes.
CAVEATS
While pytest is generally straightforward, users should be aware of a few points:
Dependency Management: pytest and its plugins must be installed via pip (e.g., pip install pytest). Ensure your testing environment has the necessary packages.
Test Discovery Nuances: pytest has specific rules for test discovery (e.g., test_*.py files, test_* functions/methods). Deviating from these conventions requires explicit configuration.
Overuse of Fixtures: While fixtures are powerful, overly complex or deeply nested fixtures can sometimes make tests harder to read and debug.
Parallelization Setup: For large test suites, parallel execution via pytest-xdist is highly beneficial but requires an additional pip install pytest-xdist.
TEST DISCOVERY RULES
By default, pytest finds tests in test_*.py or *_test.py files, functions starting with test_, and methods starting with test_ inside classes not derived from unittest.TestCase (unless specified).
FIXTURE SYSTEM
pytest fixtures provide a powerful and flexible way to set up and tear down test environments. They are defined as functions and can be shared across tests, modules, or even sessions, promoting code reuse and clear separation of concerns.
PLUGIN ECOSYSTEM
A core strength of pytest is its extensive plugin system, allowing developers to extend its functionality easily. Popular plugins include pytest-cov (for coverage), pytest-mock (for mocking), and pytest-html (for HTML reports), significantly enhancing testing workflows.
HISTORY
pytest originated in 2004 as `py.test`, part of the larger `py` library by Holger Krekel. It quickly gained traction for its simplicity, extensibility, and less boilerplate-heavy approach compared to its contemporaries like Python's `unittest`. Over the years, it evolved into a standalone project, shedding the `py.` prefix to become simply `pytest`. Its adoption significantly increased due to its powerful fixture system, assert rewriting, and a vibrant plugin ecosystem, making it the de-facto standard for Python testing for many developers and organizations by the 2010s. Continuous development ensures it remains a modern and robust testing solution.