From e4d64e643acb1cd6218fc61910ab6266d3da7573 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 11 Sep 2023 12:52:49 -0700 Subject: [PATCH] add --shorten-output-lines option so users can change how much is shown --- pytest_output_to_files.py | 40 +++++++-- tests/test_output_to_files.py | 155 +++++++++++++++++++++++++--------- 2 files changed, 148 insertions(+), 47 deletions(-) diff --git a/pytest_output_to_files.py b/pytest_output_to_files.py index 7be7ba0..b6c4c37 100644 --- a/pytest_output_to_files.py +++ b/pytest_output_to_files.py @@ -12,11 +12,11 @@ if os.name != 'posix': raise ValueError( f"{sys.platform} is not supported by pytest-output-to-files") -_DEFAULT_LINE_LIMIT = 500 +_DEFAULT_LINE_LIMIT = 1000 class _Capture: - def __init__(self, target_attr, line_limit=_DEFAULT_LINE_LIMIT, + def __init__(self, target_attr, line_limit, chunk_size=1 << 16): # type: (str, int, int) -> None self.__target_attr = target_attr @@ -157,14 +157,14 @@ class _Capture: # type: () -> str assert self.__file is not None, "can't be called without file" start_lines, start_hit_eof = self.__read_lines_at( - line_limit=self.__line_limit * 2, pos=0, backwards=False) + line_limit=self.__line_limit, pos=0, backwards=False) if start_hit_eof: return start_lines.decode("utf-8", errors="replace") - p = self.__lines_from_start(start_lines, self.__line_limit) + p = self.__lines_from_start(start_lines, (self.__line_limit + 1) // 2) start_lines = start_lines[:p] file_length = self.__file.seek(0, os.SEEK_END) end_lines, _ = self.__read_lines_at( - line_limit=self.__line_limit, pos=file_length, backwards=True) + line_limit=self.__line_limit // 2, pos=file_length, backwards=True) if start_lines.endswith(b"\n"): start_lines = start_lines[:-1] if end_lines.endswith(b"\n"): @@ -209,12 +209,12 @@ class _Capture: class _OutputToFilesPlugin: - def __init__(self, output_dir): + def __init__(self, output_dir, line_limit): # type: (str) -> None self.output_dir = Path(output_dir) self.__captures = { - "stdout": _Capture("stdout"), - "stderr": _Capture("stderr"), + "stdout": _Capture("stdout", line_limit=line_limit), + "stderr": _Capture("stderr", line_limit=line_limit), } def __repr__(self): @@ -298,6 +298,19 @@ def pytest_addoption(parser): help=('shorten test outputs by storing them in files in DIR and ' 'returning just the first/last few lines')) + group.addoption( + '--shorten-output-lines', + action='store', + metavar="LINES", + help=('change the number of lines shown by the\n' + '--shorten-output-dir option')) + + parser.addini( + 'shorten-output-lines', + default=str(_DEFAULT_LINE_LIMIT), + help=('change the number of lines shown by the\n' + '--shorten-output-dir option')) + def pytest_configure(config): # type: (pytest.Config) -> None @@ -306,6 +319,15 @@ def pytest_configure(config): output_dir = config.getoption('--shorten-output-dir') if output_dir is None: output_dir = config.getini('shorten-output-dir') + line_limit = config.getoption('--shorten-output-lines') + if line_limit is None: + line_limit = config.getini('shorten-output-lines') + assert isinstance(line_limit, str), "invalid shorten-output-lines" + try: + line_limit = int(line_limit) + except ValueError as e: + raise ValueError("invalid shorten-output-lines") from e if output_dir != "": assert isinstance(output_dir, str), "invalid shorten-output-dir" - config.pluginmanager.register(_OutputToFilesPlugin(output_dir)) + config.pluginmanager.register(_OutputToFilesPlugin( + output_dir, line_limit=line_limit)) diff --git a/tests/test_output_to_files.py b/tests/test_output_to_files.py index 13cf6e7..a7854a0 100644 --- a/tests/test_output_to_files.py +++ b/tests/test_output_to_files.py @@ -16,12 +16,15 @@ def test_help_message(testdir): '*shorten test outputs by storing them in files in DIR and*', '*returning just the first/last few lines. disable by*', '*using --shorten-output-dir=""*', + '*--shorten-output-lines=LINES*', + '*change the number of lines shown by the*', + '*--shorten-output-dir option*', ]) def do_stdout_stderr_check(testdir, additional_args, stdout_lines, - stderr_lines, enabled): - # type: (pytest.Testdir, list[str], int, int, bool) -> pytest.RunResult + stderr_lines, enabled, line_limit): + # type: (pytest.Testdir, list[str], int, int, bool, int) -> pytest.RunResult testdir.makepyfile(test_print=f""" import sys @@ -47,17 +50,17 @@ def do_stdout_stderr_check(testdir, additional_args, stdout_lines, lines = ['*--- Captured stdout call ---*'] hr = '-' * 50 - if enabled and stdout_lines >= 2 * _DEFAULT_LINE_LIMIT: + if enabled and stdout_lines >= line_limit: trimmed_msg = ("Output Trimmed, Full output in: " "test-out/test_print_py/test_print/call-stdout.txt") lines.append(trimmed_msg) lines.append(hr) - for i in range(_DEFAULT_LINE_LIMIT): + for i in range((line_limit + 1) // 2): lines.append(f'in stdout {i}') lines.append(hr) lines.append(trimmed_msg) lines.append(hr) - for i in range(stdout_lines - _DEFAULT_LINE_LIMIT, stdout_lines): + for i in range(stdout_lines - line_limit // 2, stdout_lines): lines.append(f'in stdout {i}') lines.append(hr) lines.append(trimmed_msg) @@ -65,17 +68,17 @@ def do_stdout_stderr_check(testdir, additional_args, stdout_lines, for i in range(stdout_lines): lines.append(f'in stdout {i}') lines.append('*--- Captured stderr call ---*') - if enabled and stderr_lines >= 2 * _DEFAULT_LINE_LIMIT: + if enabled and stderr_lines >= line_limit: trimmed_msg = ("Output Trimmed, Full output in: " "test-out/test_print_py/test_print/call-stderr.txt") lines.append(trimmed_msg) lines.append(hr) - for i in range(_DEFAULT_LINE_LIMIT): + for i in range((line_limit + 1) // 2): lines.append(f'in stderr {i}') lines.append(hr) lines.append(trimmed_msg) lines.append(hr) - for i in range(stderr_lines - _DEFAULT_LINE_LIMIT, stderr_lines): + for i in range(stderr_lines - line_limit // 2, stderr_lines): lines.append(f'in stderr {i}') lines.append(hr) lines.append(trimmed_msg) @@ -112,18 +115,21 @@ def test_ini_setting(testdir): shorten-output-dir = test-out """) - do_stdout_stderr_check(testdir, [], 1, 1, True) + do_stdout_stderr_check(testdir, [], 1, 1, True, + line_limit=_DEFAULT_LINE_LIMIT) def test_nothing(testdir): # type: (pytest.Testdir) -> None - do_stdout_stderr_check(testdir, [], 1, 1, False) + do_stdout_stderr_check(testdir, [], 1, 1, False, + line_limit=_DEFAULT_LINE_LIMIT) def test_arg(testdir): # type: (pytest.Testdir) -> None do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], 1, 1, True) + testdir, ["--shorten-output-dir=test-out"], 1, 1, True, + line_limit=_DEFAULT_LINE_LIMIT) def test_arg_override_ini(testdir): @@ -134,7 +140,8 @@ def test_arg_override_ini(testdir): """) do_stdout_stderr_check( - testdir, ["--shorten-output-dir="], 1, 1, False) + testdir, ["--shorten-output-dir="], 1, 1, False, + line_limit=_DEFAULT_LINE_LIMIT) def test_disable_capture(testdir): @@ -168,81 +175,153 @@ def test_disable_capture(testdir): def test_20k_disabled(testdir): # type: (pytest.Testdir) -> None - do_stdout_stderr_check(testdir, [], 20000, 20000, False) + do_stdout_stderr_check(testdir, [], 20000, 20000, False, + line_limit=_DEFAULT_LINE_LIMIT) def test_20k(testdir): # type: (pytest.Testdir) -> None do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], 20000, 20000, True) + testdir, ["--shorten-output-dir=test-out"], 20000, 20000, True, + line_limit=_DEFAULT_LINE_LIMIT) def test_21k(testdir): # type: (pytest.Testdir) -> None do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], 21000, 21000, True) + testdir, ["--shorten-output-dir=test-out"], 21000, 21000, True, + line_limit=_DEFAULT_LINE_LIMIT) def test_22k(testdir): # type: (pytest.Testdir) -> None do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], 22000, 22000, True) + testdir, ["--shorten-output-dir=test-out"], 22000, 22000, True, + line_limit=_DEFAULT_LINE_LIMIT) -def test_1x(testdir): +def test_half(testdir): # type: (pytest.Testdir) -> None - lines = _DEFAULT_LINE_LIMIT + lines = _DEFAULT_LINE_LIMIT // 2 do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], lines, lines, True) + testdir, ["--shorten-output-dir=test-out"], lines, lines, True, + line_limit=_DEFAULT_LINE_LIMIT) -def test_50_percent_more(testdir): +def test_75_percent(testdir): # type: (pytest.Testdir) -> None - lines = _DEFAULT_LINE_LIMIT + _DEFAULT_LINE_LIMIT // 2 + lines = _DEFAULT_LINE_LIMIT * 3 // 4 do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], lines, lines, True) + testdir, ["--shorten-output-dir=test-out"], lines, lines, True, + line_limit=_DEFAULT_LINE_LIMIT) -def test_2x_minus_two(testdir): +def test_limit_minus_two(testdir): # type: (pytest.Testdir) -> None - lines = _DEFAULT_LINE_LIMIT * 2 - 2 + lines = _DEFAULT_LINE_LIMIT - 2 do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], lines, lines, True) + testdir, ["--shorten-output-dir=test-out"], lines, lines, True, + line_limit=_DEFAULT_LINE_LIMIT) -def test_2x_minus_one(testdir): +def test_limit_minus_one(testdir): # type: (pytest.Testdir) -> None - lines = _DEFAULT_LINE_LIMIT * 2 - 1 + lines = _DEFAULT_LINE_LIMIT - 1 do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], lines, lines, True) + testdir, ["--shorten-output-dir=test-out"], lines, lines, True, + line_limit=_DEFAULT_LINE_LIMIT) -def test_2x(testdir): +def test_limit(testdir): # type: (pytest.Testdir) -> None - lines = _DEFAULT_LINE_LIMIT * 2 + lines = _DEFAULT_LINE_LIMIT do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], lines, lines, True) + testdir, ["--shorten-output-dir=test-out"], lines, lines, True, + line_limit=_DEFAULT_LINE_LIMIT) -def test_2x_plus_one(testdir): +def test_limit_plus_one(testdir): # type: (pytest.Testdir) -> None - lines = _DEFAULT_LINE_LIMIT * 2 + 1 + lines = _DEFAULT_LINE_LIMIT + 1 do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], lines, lines, True) + testdir, ["--shorten-output-dir=test-out"], lines, lines, True, + line_limit=_DEFAULT_LINE_LIMIT) -def test_2x_plus_two(testdir): +def test_limit_plus_two(testdir): # type: (pytest.Testdir) -> None - lines = _DEFAULT_LINE_LIMIT * 2 + 2 + lines = _DEFAULT_LINE_LIMIT + 2 do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], lines, lines, True) + testdir, ["--shorten-output-dir=test-out"], lines, lines, True, + line_limit=_DEFAULT_LINE_LIMIT) def test_1M(testdir): # type: (pytest.Testdir) -> None lines = 1_000_000 do_stdout_stderr_check( - testdir, ["--shorten-output-dir=test-out"], lines, lines, True) + testdir, ["--shorten-output-dir=test-out"], lines, lines, True, + line_limit=_DEFAULT_LINE_LIMIT) + + +def test_small_limit_minus_one(testdir): + # type: (pytest.Testdir) -> None + line_limit = 50 + lines = line_limit - 1 + do_stdout_stderr_check(testdir, + ["--shorten-output-dir=test-out", + f"--shorten-output-lines={line_limit}"], + lines, lines, True, line_limit=line_limit) + + +def test_small_limit(testdir): + # type: (pytest.Testdir) -> None + line_limit = 50 + lines = line_limit + do_stdout_stderr_check(testdir, + ["--shorten-output-dir=test-out", + f"--shorten-output-lines={line_limit}"], + lines, lines, True, line_limit=line_limit) + + +def test_small_limit_plus_one(testdir): + # type: (pytest.Testdir) -> None + line_limit = 50 + lines = line_limit + 1 + do_stdout_stderr_check(testdir, + ["--shorten-output-dir=test-out", + f"--shorten-output-lines={line_limit}"], + lines, lines, True, line_limit=line_limit) + + +def test_large_limit_minus_one(testdir): + # type: (pytest.Testdir) -> None + line_limit = 200 + lines = line_limit - 1 + do_stdout_stderr_check(testdir, + ["--shorten-output-dir=test-out", + f"--shorten-output-lines={line_limit}"], + lines, lines, True, line_limit=line_limit) + + +def test_large_limit(testdir): + # type: (pytest.Testdir) -> None + line_limit = 200 + lines = line_limit + do_stdout_stderr_check(testdir, + ["--shorten-output-dir=test-out", + f"--shorten-output-lines={line_limit}"], + lines, lines, True, line_limit=line_limit) + + +def test_large_limit_plus_one(testdir): + # type: (pytest.Testdir) -> None + line_limit = 200 + lines = line_limit + 1 + do_stdout_stderr_check(testdir, + ["--shorten-output-dir=test-out", + f"--shorten-output-lines={line_limit}"], + lines, lines, True, line_limit=line_limit) if __name__ == "__main__": -- 2.30.2