-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Integrate pytest-subtests #13738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
nicoddemus
merged 25 commits into
pytest-dev:main
from
nicoddemus:integrate-pytest-subtests
Nov 1, 2025
+1,727
−24
Merged
Integrate pytest-subtests #13738
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
8fb305a
Add pytest-subtests files changes
nicoddemus 9d3eba5
subtests: remove direct pytest import
nicoddemus 728d802
Force using xdist plugin and fix linting
nicoddemus 6a5569f
Replace attr by dataclass
nicoddemus ff446c0
Add docs
nicoddemus 4befec0
Cleanup internal hacks
nicoddemus 35db790
Code review
nicoddemus 7ba2b51
Code review
nicoddemus 13caaa6
Docs
nicoddemus a0ab30f
Make top-level tests fail when there are failing subtests
nicoddemus 2fcbfa6
Minor code review
nicoddemus 1d4abb1
Replace separate plugin by config.stash
nicoddemus 65e6b1c
Mention pytest-subtests in the docs
nicoddemus de80614
More code review
nicoddemus fee714f
Remove update_report
nicoddemus c1925d0
Do not suppress pytest.exit() or keyboard interrupt when working with…
nicoddemus 0f3251a
Forward log_level from plugin
nicoddemus 10a9ddb
Add test case for nested subtests
nicoddemus 9c52146
Add "verbosity_subtests" option and revamp tests
nicoddemus 681c139
Update doc/en/reference/reference.rst
nicoddemus fd4c0bb
Mention verbosity_subtests
nicoddemus 0411e6b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 06c1780
Add test for subtest skip
nicoddemus d6ec3ce
Ignore case unreachable for coverage
nicoddemus a8c23ec
Improve coverage
nicoddemus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| **Support for subtests** has been added. | ||
|
|
||
| :ref:`subtests <subtests>` are an alternative to parametrization, useful in situations where the parametrization values are not all known at collection time. | ||
|
|
||
| **Example** | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| def contains_docstring(p: Path) -> bool: | ||
| """Return True if the given Python file contains a top-level docstring.""" | ||
| ... | ||
|
|
||
|
|
||
| def test_py_files_contain_docstring(subtests: pytest.Subtests) -> None: | ||
| for path in Path.cwd().glob("*.py"): | ||
| with subtests.test(path=str(path)): | ||
| assert contains_docstring(path) | ||
|
|
||
|
|
||
| Each assert failure or error is caught by the context manager and reported individually, giving a clear picture of all files that are missing a docstring. | ||
|
|
||
| In addition, :meth:`unittest.TestCase.subTest` is now also supported. | ||
|
|
||
| This feature was originally implemented as a separate plugin in `pytest-subtests <https://github.com/pytest-dev/pytest-subtests>`__, but since then has been merged into the core. | ||
|
|
||
| .. note:: | ||
|
|
||
| This feature is experimental and will likely evolve in future releases. By that we mean that we might change how subtests are reported on failure, but the functionality and how to use it are stable. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ Core pytest functionality | |
| fixtures | ||
| mark | ||
| parametrize | ||
| subtests | ||
| tmp_path | ||
| monkeypatch | ||
| doctest | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| .. _subtests: | ||
|
|
||
| How to use subtests | ||
| =================== | ||
|
|
||
| .. versionadded:: 9.0 | ||
|
|
||
| .. note:: | ||
|
|
||
| This feature is experimental. Its behavior, particularly how failures are reported, may evolve in future releases. However, the core functionality and usage are considered stable. | ||
|
|
||
| pytest allows for grouping assertions within a normal test, known as *subtests*. | ||
|
|
||
| Subtests are an alternative to parametrization, particularly useful when the exact parametrization values are not known at collection time. | ||
|
|
||
|
|
||
| .. code-block:: python | ||
|
|
||
| # content of test_subtest.py | ||
|
|
||
|
|
||
| def test(subtests): | ||
| for i in range(5): | ||
| with subtests.test(msg="custom message", i=i): | ||
| assert i % 2 == 0 | ||
|
|
||
| Each assertion failure or error is caught by the context manager and reported individually: | ||
nicoddemus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| .. code-block:: pytest | ||
|
|
||
| $ pytest -q test_subtest.py | ||
|
|
||
|
|
||
| In the output above: | ||
|
|
||
| * Subtest failures are reported as ``SUBFAILED``. | ||
| * Subtests are reported first and the "top-level" test is reported at the end on its own. | ||
|
|
||
| Note that it is possible to use ``subtests`` multiple times in the same test, or even mix and match with normal assertions | ||
| outside the ``subtests.test`` block: | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| def test(subtests): | ||
| for i in range(5): | ||
| with subtests.test("stage 1", i=i): | ||
| assert i % 2 == 0 | ||
|
|
||
| assert func() == 10 | ||
|
|
||
| for i in range(10, 20): | ||
| with subtests.test("stage 2", i=i): | ||
| assert i % 2 == 0 | ||
|
|
||
| .. note:: | ||
|
|
||
| See :ref:`parametrize` for an alternative to subtests. | ||
|
|
||
|
|
||
| Verbosity | ||
| --------- | ||
|
|
||
| By default, only **subtest failures** are shown. Higher verbosity levels (``-v``) will also show progress output for **passed** subtests. | ||
|
|
||
| It is possible to control the verbosity of subtests by setting :confval:`verbosity_subtests`. | ||
|
|
||
|
|
||
| Typing | ||
| ------ | ||
|
|
||
| :class:`pytest.Subtests` is exported so it can be used in type annotations: | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| def test(subtests: pytest.Subtests) -> None: ... | ||
|
|
||
| .. _parametrize_vs_subtests: | ||
|
|
||
| Parametrization vs Subtests | ||
| --------------------------- | ||
|
|
||
| While :ref:`traditional pytest parametrization <parametrize>` and ``subtests`` are similar, they have important differences and use cases. | ||
|
|
||
nicoddemus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Parametrization | ||
| ~~~~~~~~~~~~~~~ | ||
|
|
||
| * Happens at collection time. | ||
| * Generates individual tests. | ||
| * Parametrized tests can be referenced from the command line. | ||
| * Plays well with plugins that handle test execution, such as ``--last-failed``. | ||
| * Ideal for decision table testing. | ||
|
|
||
| Subtests | ||
| ~~~~~~~~ | ||
|
|
||
| * Happen during test execution. | ||
| * Are not known at collection time. | ||
| * Can be generated dynamically. | ||
| * Cannot be referenced individually from the command line. | ||
| * Plugins that handle test execution cannot target individual subtests. | ||
| * An assertion failure inside a subtest does not interrupt the test, letting users see all failures in the same report. | ||
|
|
||
|
|
||
| .. note:: | ||
|
|
||
| This feature was originally implemented as a separate plugin in `pytest-subtests <https://github.com/pytest-dev/pytest-subtests>`__, but since ``9.0`` has been merged into the core. | ||
|
|
||
| The core implementation should be compatible to the plugin implementation, except it does not contain custom command-line options to control subtest output. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,6 +25,7 @@ | |
| "pytest_catchlog", | ||
| "pytest_capturelog", | ||
| "pytest_faulthandler", | ||
| "pytest_subtests", | ||
| } | ||
|
|
||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.