all tests pass!
[pytest-output-to-files.git] / tests / test_output_to_files.py
diff --git a/tests/test_output_to_files.py b/tests/test_output_to_files.py
new file mode 100644 (file)
index 0000000..13cf6e7
--- /dev/null
@@ -0,0 +1,249 @@
+import pytest
+import sys
+from pathlib import Path
+from pytest_output_to_files import _DEFAULT_LINE_LIMIT
+
+
+def test_help_message(testdir):
+    # type: (pytest.Testdir) -> None
+    result = testdir.runpytest(
+        '--help',
+    )
+    # fnmatch_lines does an assertion internally
+    result.stdout.fnmatch_lines([
+        'shortening output:',
+        '*--shorten-output-dir=DIR*',
+        '*shorten test outputs by storing them in files in DIR and*',
+        '*returning just the first/last few lines. disable by*',
+        '*using --shorten-output-dir=""*',
+    ])
+
+
+def do_stdout_stderr_check(testdir, additional_args, stdout_lines,
+                           stderr_lines, enabled):
+    # type: (pytest.Testdir, list[str], int, int, bool) -> pytest.RunResult
+    testdir.makepyfile(test_print=f"""
+        import sys
+
+        def test_print():
+            for i in range({stdout_lines}):
+                print(f'in stdout {{i}}')
+            for i in range({stderr_lines}):
+                print(f'in stderr {{i}}', file=sys.stderr)
+            assert False
+    """)
+
+    full_stdout = ''.join(f'in stdout {i}\n' for i in range(stdout_lines))
+    full_stderr = ''.join(f'in stderr {i}\n' for i in range(stderr_lines))
+
+    result = testdir.runpytest('-v', *additional_args)
+
+    test_out_path = Path(testdir.tmpdir)
+    test_out_path /= "test-out"
+    test_print_path = test_out_path / "test_print_py"
+    test_print_path /= "test_print"
+    call_stdout_path = test_print_path / "call-stdout.txt"
+    call_stderr_path = test_print_path / "call-stderr.txt"
+
+    lines = ['*--- Captured stdout call ---*']
+    hr = '-' * 50
+    if enabled and stdout_lines >= 2 * _DEFAULT_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):
+            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):
+            lines.append(f'in stdout {i}')
+        lines.append(hr)
+        lines.append(trimmed_msg)
+    else:
+        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:
+        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):
+            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):
+            lines.append(f'in stderr {i}')
+        lines.append(hr)
+        lines.append(trimmed_msg)
+    else:
+        for i in range(stderr_lines):
+            lines.append(f'in stderr {i}')
+    lines.append("*====*")
+
+    result.stdout.fnmatch_lines(lines, consecutive=True)
+
+    result.stdout.fnmatch_lines([
+        'FAILED test_print.py::test_print *',
+    ])
+
+    if enabled:
+        for empty_file in ("setup-stdout.txt", "setup-stderr.txt",
+                           "teardown-stdout.txt", "teardown-stderr.txt"):
+            assert (test_print_path / empty_file).read_text("utf-8") == ""
+        assert call_stdout_path.read_text("utf-8") == full_stdout
+        assert call_stderr_path.read_text("utf-8") == full_stderr
+        call_stdout_path.unlink()  # remove big files
+        call_stderr_path.unlink()  # remove big files
+    else:
+        assert not test_out_path.exists()
+    assert result.ret != 0
+
+    return result
+
+
+def test_ini_setting(testdir):
+    # type: (pytest.Testdir) -> None
+    testdir.makeini("""
+        [pytest]
+        shorten-output-dir = test-out
+    """)
+
+    do_stdout_stderr_check(testdir, [], 1, 1, True)
+
+
+def test_nothing(testdir):
+    # type: (pytest.Testdir) -> None
+    do_stdout_stderr_check(testdir, [], 1, 1, False)
+
+
+def test_arg(testdir):
+    # type: (pytest.Testdir) -> None
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir=test-out"], 1, 1, True)
+
+
+def test_arg_override_ini(testdir):
+    # type: (pytest.Testdir) -> None
+    testdir.makeini("""
+        [pytest]
+        shorten-output-dir = test-out
+    """)
+
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir="], 1, 1, False)
+
+
+def test_disable_capture(testdir):
+    # type: (pytest.Testdir) -> None
+    testdir.makeini("""
+        [pytest]
+        shorten-output-dir = test-out
+    """)
+
+    testdir.makepyfile(test_print=f"""
+        import sys
+
+        def test_print():
+            print(f'in stdout')
+            print(f'in stderr', file=sys.stderr)
+            assert False
+    """)
+
+    result = testdir.runpytest('-v', '-s')
+
+    test_out_path = Path(testdir.tmpdir)
+    test_out_path /= "test-out"
+
+    assert not test_out_path.exists()
+
+    result.stdout.fnmatch_lines(['test_print.py::test_print*in stdout'])
+    result.stderr.fnmatch_lines(['in stderr'])
+
+    assert result.ret != 0
+
+
+def test_20k_disabled(testdir):
+    # type: (pytest.Testdir) -> None
+    do_stdout_stderr_check(testdir, [], 20000, 20000, False)
+
+
+def test_20k(testdir):
+    # type: (pytest.Testdir) -> None
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir=test-out"], 20000, 20000, True)
+
+
+def test_21k(testdir):
+    # type: (pytest.Testdir) -> None
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir=test-out"], 21000, 21000, True)
+
+
+def test_22k(testdir):
+    # type: (pytest.Testdir) -> None
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir=test-out"], 22000, 22000, True)
+
+
+def test_1x(testdir):
+    # type: (pytest.Testdir) -> None
+    lines = _DEFAULT_LINE_LIMIT
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir=test-out"], lines, lines, True)
+
+
+def test_50_percent_more(testdir):
+    # type: (pytest.Testdir) -> None
+    lines = _DEFAULT_LINE_LIMIT + _DEFAULT_LINE_LIMIT // 2
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir=test-out"], lines, lines, True)
+
+
+def test_2x_minus_two(testdir):
+    # type: (pytest.Testdir) -> None
+    lines = _DEFAULT_LINE_LIMIT * 2 - 2
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir=test-out"], lines, lines, True)
+
+
+def test_2x_minus_one(testdir):
+    # type: (pytest.Testdir) -> None
+    lines = _DEFAULT_LINE_LIMIT * 2 - 1
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir=test-out"], lines, lines, True)
+
+
+def test_2x(testdir):
+    # type: (pytest.Testdir) -> None
+    lines = _DEFAULT_LINE_LIMIT * 2
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir=test-out"], lines, lines, True)
+
+
+def test_2x_plus_one(testdir):
+    # type: (pytest.Testdir) -> None
+    lines = _DEFAULT_LINE_LIMIT * 2 + 1
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir=test-out"], lines, lines, True)
+
+
+def test_2x_plus_two(testdir):
+    # type: (pytest.Testdir) -> None
+    lines = _DEFAULT_LINE_LIMIT * 2 + 2
+    do_stdout_stderr_check(
+        testdir, ["--shorten-output-dir=test-out"], lines, lines, True)
+
+
+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)
+
+
+if __name__ == "__main__":
+    sys.exit(pytest.main())