diff --git a/changelog/12713.feature.rst b/changelog/12713.feature.rst new file mode 100644 index 0000000000..b4e9270bcc --- /dev/null +++ b/changelog/12713.feature.rst @@ -0,0 +1,5 @@ +Add `--force-short-summary` option to force condensed summary output regardless of verbosity level + +Adds ability to still see condensed summary output of failures for quick reference in log files from job outputs. Especially useful if non-condensed output is very verbose. + +Also includes full fix for :issue:`11777` where sequences were still being shortened even with `-vv` verbosity. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 41e3d27139..2e606d1903 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -28,6 +28,7 @@ from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE from _pytest._io.saferepr import saferepr +from _pytest._io.saferepr import saferepr_unlimited from _pytest._version import version from _pytest.assertion import util from _pytest.config import Config @@ -433,6 +434,8 @@ def _saferepr(obj: object) -> str: return obj.__name__ maxsize = _get_maxsize_for_saferepr(util._config) + if not maxsize: + return saferepr_unlimited(obj).replace("\n", "\\n") return saferepr(obj, maxsize=maxsize).replace("\n", "\\n") diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 348a78af9f..f1373dc658 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -161,6 +161,13 @@ def pytest_addoption(parser: Parser) -> None: default=True, help="Do not fold skipped tests in short summary.", ) + group._addoption( + "--force-short-summary", + action="store_true", + dest="force_short_summary", + default=False, + help="Force condensed summary output regardless of verbosity level.", + ) group._addoption( "-q", "--quiet", @@ -1467,7 +1474,9 @@ def _get_line_with_reprcrash_message( except AttributeError: pass else: - if running_on_ci() or config.option.verbose >= 2: + if ( + running_on_ci() or config.option.verbose >= 2 + ) and not config.option.force_short_summary: msg = f" - {msg}" else: available_width = tw.fullwidth - line_width diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 6fa04be28b..a572becb9b 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2520,6 +2520,51 @@ def test(): ) +def test_full_sequence_print_with_vv( + monkeypatch: MonkeyPatch, pytester: Pytester +) -> None: + monkeypatch.setattr(_pytest.terminal, "running_on_ci", lambda: False) + + pytester.makepyfile( + """ + def test_len_list(): + l = list(range(10)) + assert len(l) == 9 + + def test_len_dict(): + d = dict(zip(range(10), range(10))) + assert len(d) == 9 + """ + ) + + result = pytester.runpytest("-vv") + assert result.ret == 1 + result.stdout.fnmatch_lines( + [ + "*short test summary info*", + f"*{list(range(10))}*", + f"*{dict(zip(range(10), range(10)))}*", + ] + ) + + +def test_force_short_summary(monkeypatch: MonkeyPatch, pytester: Pytester) -> None: + monkeypatch.setattr(_pytest.terminal, "running_on_ci", lambda: False) + + pytester.makepyfile( + """ + def test(): + assert "a\\n" * 10 == "" + """ + ) + + result = pytester.runpytest("-vv", "--force-short-summary") + assert result.ret == 1 + result.stdout.fnmatch_lines( + ["*short test summary info*", "*AssertionError: assert 'a\\na\\na\\na..."] + ) + + @pytest.mark.parametrize( "seconds, expected", [