add --shorten-output-lines option so users can change how much is shown master
authorJacob Lifshay <programmerjake@gmail.com>
Mon, 11 Sep 2023 19:52:49 +0000 (12:52 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Mon, 11 Sep 2023 19:52:49 +0000 (12:52 -0700)
pytest_output_to_files.py
tests/test_output_to_files.py

index 7be7ba056a7fb73ea2dd584b466693028c9c83e5..b6c4c371fba7fc27778e9d2856476ca764f8d7b5 100644 (file)
@@ -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))
index 13cf6e7c1a085f5456998f15f8308261c6fe096a..a7854a0ae2cf2b3da2372890df5de5df1de2bd0c 100644 (file)
@@ -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__":