From a2d0f6576206774d3b80a81c109d9281107eb273 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Thu, 26 Jun 2025 00:36:47 +0200 Subject: [PATCH 01/10] add --no-subtests-reports opt Signed-off-by: Giampaolo Rodola --- src/pytest_subtests/plugin.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/pytest_subtests/plugin.py b/src/pytest_subtests/plugin.py index d31c711..37a140b 100644 --- a/src/pytest_subtests/plugin.py +++ b/src/pytest_subtests/plugin.py @@ -46,6 +46,15 @@ def pytest_addoption(parser: pytest.Parser) -> None: default=False, help="Disables subtest output 'dots' in non-verbose mode (EXPERIMENTAL)", ) + group.addoption( + "--no-subtests-reports", + action="store_true", + dest="no_subtests_reports", + default=False, + help="Disable subtest output unless it's a failed subtest (EXPERIMENTAL)", + ) + + @attr.s @@ -459,9 +468,12 @@ def pytest_report_teststatus( outcome = report.outcome description = report.sub_test_description() + no_output = ("", "", "") if hasattr(report, "wasxfail"): - if outcome == "skipped": + if config.option.no_subtests_reports and category != "xfailed": + return no_output + elif outcome == "skipped": category = "xfailed" short = "y" # x letter is used for regular xfail, y for subtest xfail status = "SUBXFAIL" @@ -474,8 +486,12 @@ def pytest_report_teststatus( # the correct outcome. Pytest expects the call outcome to be either skipped or passed in case of xfail. # Let's pass this report to the next hook. return None + short = "" if config.option.no_subtests_shortletter else short return f"subtests {category}", short, f"{description} {status}" + + if config.option.no_subtests_reports and outcome != "failed": + return no_output elif report.passed: short = "" if config.option.no_subtests_shortletter else "," return f"subtests {outcome}", short, f"{description} SUBPASS" From 92b7871bc6fcc8031f595dd7bb0ce613db260c10 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Thu, 26 Jun 2025 00:40:38 +0200 Subject: [PATCH 02/10] update CHANGELOG Signed-off-by: Giampaolo Rodola --- CHANGELOG.rst | 8 ++++++++ src/pytest_subtests/plugin.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6a94260..05e60d1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ CHANGELOG ========= +0.14.3 (UNRELEASED) +------------------- + +* Added experimental ``--no-subtest-reports`` CLI option. This disables + subtests output unless it's a failed subtest. (`#198`_) + +.. _#198: https://github.com/pytest-dev/pytest-subtests/pull/198 + 0.14.2 ------ diff --git a/src/pytest_subtests/plugin.py b/src/pytest_subtests/plugin.py index 37a140b..08200fd 100644 --- a/src/pytest_subtests/plugin.py +++ b/src/pytest_subtests/plugin.py @@ -51,7 +51,7 @@ def pytest_addoption(parser: pytest.Parser) -> None: action="store_true", dest="no_subtests_reports", default=False, - help="Disable subtest output unless it's a failed subtest (EXPERIMENTAL)", + help="Disables subtest output unless it's a failed subtest (EXPERIMENTAL)", ) From 11c7efa4bf4fa2ebbb93bbd62fa51b63ee8cd4bf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 25 Jun 2025 22:42:41 +0000 Subject: [PATCH 03/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/pytest_subtests/plugin.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pytest_subtests/plugin.py b/src/pytest_subtests/plugin.py index 08200fd..4de777d 100644 --- a/src/pytest_subtests/plugin.py +++ b/src/pytest_subtests/plugin.py @@ -55,8 +55,6 @@ def pytest_addoption(parser: pytest.Parser) -> None: ) - - @attr.s class SubTestContext: msg: str | None = attr.ib() From 5bd54ae6c7236807598b7a58d21caa63e8b9c0ea Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Thu, 26 Jun 2025 00:47:59 +0200 Subject: [PATCH 04/10] add XXXX-XX-XX date stub in CHANGELOG Signed-off-by: Giampaolo Rodola --- CHANGELOG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 05e60d1..c486c23 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,8 @@ CHANGELOG 0.14.3 (UNRELEASED) ------------------- +*XXXX-XX-XX* + * Added experimental ``--no-subtest-reports`` CLI option. This disables subtests output unless it's a failed subtest. (`#198`_) From ead068c662b4deb41982703414991223429ca820 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Thu, 26 Jun 2025 00:57:30 +0200 Subject: [PATCH 05/10] fix mypy warning Signed-off-by: Giampaolo Rodola --- src/pytest_subtests/plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pytest_subtests/plugin.py b/src/pytest_subtests/plugin.py index 4de777d..1b650a0 100644 --- a/src/pytest_subtests/plugin.py +++ b/src/pytest_subtests/plugin.py @@ -469,7 +469,7 @@ def pytest_report_teststatus( no_output = ("", "", "") if hasattr(report, "wasxfail"): - if config.option.no_subtests_reports and category != "xfailed": + if config.option.no_subtests_reports and outcome != "skipped": return no_output elif outcome == "skipped": category = "xfailed" From 05f03d950622442cba254e0446eb22d840b1891f Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Thu, 26 Jun 2025 00:58:32 +0200 Subject: [PATCH 06/10] rm useless new line Signed-off-by: Giampaolo Rodola --- src/pytest_subtests/plugin.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pytest_subtests/plugin.py b/src/pytest_subtests/plugin.py index 1b650a0..956939f 100644 --- a/src/pytest_subtests/plugin.py +++ b/src/pytest_subtests/plugin.py @@ -484,7 +484,6 @@ def pytest_report_teststatus( # the correct outcome. Pytest expects the call outcome to be either skipped or passed in case of xfail. # Let's pass this report to the next hook. return None - short = "" if config.option.no_subtests_shortletter else short return f"subtests {category}", short, f"{description} {status}" From 57cc927a82b21d30078d91be0c87f8df83833faa Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Sun, 3 Aug 2025 19:37:00 +0200 Subject: [PATCH 07/10] add test --- tests/test_subtests.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test_subtests.py b/tests/test_subtests.py index bd5cef9..0988a84 100644 --- a/tests/test_subtests.py +++ b/tests/test_subtests.py @@ -156,6 +156,25 @@ def test_typing_exported(subtests: SubTests) -> None: expected_lines += ["* 1 passed *"] result.stdout.fnmatch_lines(expected_lines) + def test_no_subtests_reports(self, pytester: pytest.Pytester, mode: Literal["normal", "xdist"]): + pytester.makepyfile( + """ + import pytest + + def test_foo(subtests): + for i in range(5): + with subtests.test(msg="custom", i=i): + pass + """ + ) + expected_lines = [ + "*collected 1 item*", + "*test_no_subtests_reports.py::test_foo PASSED*", + ] + + result = pytester.runpytest("-v", "--no-subtests-reports") + result.stdout.fnmatch_lines(expected_lines) + class TestSubTest: """ From df899b8f9e42b1bf1b165492c3eff1cd90f4a433 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Aug 2025 17:37:23 +0000 Subject: [PATCH 08/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_subtests.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_subtests.py b/tests/test_subtests.py index 0988a84..353d108 100644 --- a/tests/test_subtests.py +++ b/tests/test_subtests.py @@ -156,7 +156,9 @@ def test_typing_exported(subtests: SubTests) -> None: expected_lines += ["* 1 passed *"] result.stdout.fnmatch_lines(expected_lines) - def test_no_subtests_reports(self, pytester: pytest.Pytester, mode: Literal["normal", "xdist"]): + def test_no_subtests_reports( + self, pytester: pytest.Pytester, mode: Literal["normal", "xdist"] + ): pytester.makepyfile( """ import pytest From 88a3aec0b2a2526182362f8aeb5c64f7bb71bc43 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Sun, 3 Aug 2025 19:38:37 +0200 Subject: [PATCH 09/10] make typechecker happy --- tests/test_subtests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_subtests.py b/tests/test_subtests.py index 0988a84..745cb1a 100644 --- a/tests/test_subtests.py +++ b/tests/test_subtests.py @@ -156,7 +156,7 @@ def test_typing_exported(subtests: SubTests) -> None: expected_lines += ["* 1 passed *"] result.stdout.fnmatch_lines(expected_lines) - def test_no_subtests_reports(self, pytester: pytest.Pytester, mode: Literal["normal", "xdist"]): + def test_no_subtests_reports(self, pytester: pytest.Pytester, mode: Literal["normal", "xdist"]) -> None: pytester.makepyfile( """ import pytest From 0cc43772d0c80c53ef84c904e3f957ee9d5d4edd Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 7 Aug 2025 21:29:49 -0300 Subject: [PATCH 10/10] Improve test --- tests/test_subtests.py | 45 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/tests/test_subtests.py b/tests/test_subtests.py index 6259004..2ddb0d1 100644 --- a/tests/test_subtests.py +++ b/tests/test_subtests.py @@ -169,13 +169,48 @@ def test_foo(subtests): pass """ ) - expected_lines = [ - "*collected 1 item*", - "*test_no_subtests_reports.py::test_foo PASSED*", - ] + # Without `--no-subtests-reports`, subtests are reported normally. + result = pytester.runpytest("-v") + result.stdout.fnmatch_lines( + [ + "*collected 1 item*", + "test_no_subtests_reports.py::test_foo * (i=0) SUBPASS*", + "*test_no_subtests_reports.py::test_foo PASSED*", + "* 1 passed, 5 subtests passed in*", + ] + ) + # With `--no-subtests-reports`, passing subtests are no longer reported. result = pytester.runpytest("-v", "--no-subtests-reports") - result.stdout.fnmatch_lines(expected_lines) + result.stdout.fnmatch_lines( + [ + "*collected 1 item*", + "*test_no_subtests_reports.py::test_foo PASSED*", + "* 1 passed in*", + ] + ) + result.stdout.no_fnmatch_line("*SUBPASS*") + + # Rewrite the test file so the tests fail. Even with the flag, failed subtests are still reported. + pytester.makepyfile( + """ + import pytest + + def test_foo(subtests): + for i in range(5): + with subtests.test(msg="custom", i=i): + assert False + """ + ) + result = pytester.runpytest("-v", "--no-subtests-reports") + result.stdout.fnmatch_lines( + [ + "*collected 1 item*", + "test_no_subtests_reports.py::test_foo * (i=0) SUBFAIL*", + "*test_no_subtests_reports.py::test_foo PASSED*", + "* 5 failed, 1 passed in*", + ] + ) class TestSubTest: