diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6a94260..c486c23 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,16 @@ 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`_) + +.. _#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 d31c711..956939f 100644 --- a/src/pytest_subtests/plugin.py +++ b/src/pytest_subtests/plugin.py @@ -46,6 +46,13 @@ 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="Disables subtest output unless it's a failed subtest (EXPERIMENTAL)", + ) @attr.s @@ -459,9 +466,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 outcome != "skipped": + return no_output + elif outcome == "skipped": category = "xfailed" short = "y" # x letter is used for regular xfail, y for subtest xfail status = "SUBXFAIL" @@ -476,6 +486,9 @@ def pytest_report_teststatus( 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" diff --git a/tests/test_subtests.py b/tests/test_subtests.py index bd5cef9..2ddb0d1 100644 --- a/tests/test_subtests.py +++ b/tests/test_subtests.py @@ -156,6 +156,62 @@ 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"] + ) -> None: + pytester.makepyfile( + """ + import pytest + + def test_foo(subtests): + for i in range(5): + with subtests.test(msg="custom", i=i): + pass + """ + ) + # 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( + [ + "*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: """