Skip to content

Commit 1708571

Browse files
committed
Reduce the slowest test costs without changing production behavior
Profiling with pytest --durations=10 identified four clear outliers: a debug-toggle test highlighting cmd2's source and three successful-pipe tests waiting through the production startup probe. Keep real traceback rendering but suppress source highlighting in the debug-toggle test. For successful-pipe tests, model the startup probe's timeout while preserving real subprocess I/O and completion waits. Early-exit detection remains covered by its separate deterministic test. Local parallel-run timings (Python 3.14 free-threaded, macOS): | Test | Before | After | |---------------------------------|--------|-------| | test_base_debug | 0.31s | 0.01s | | test_pipe_to_shell | 0.22s | 0.03s | | test_piping_uses_utf8 | 0.22s | 0.05s | | test_pipe_to_shell_and_redirect | 0.21s | 0.05s | Full-suite parallel time: 3.14s -> 2.61s. Full-suite serial time: 7.06s -> 6.18s. The remaining top-ten entries were around 0.05s each and were left intact. Validation: 1,864 passed, 2 skipped; coverage unchanged at 99.4%. make check and make docs-test passed.
1 parent af7db35 commit 1708571

3 files changed

Lines changed: 25 additions & 3 deletions

File tree

‎tests/conftest.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Cmd2 unit/functional testing"""
22

33
import os
4+
import subprocess
45
import sys
56
from collections.abc import Callable
67
from contextlib import redirect_stderr
@@ -110,6 +111,24 @@ def fixed_terminal_size(monkeypatch: pytest.MonkeyPatch) -> None:
110111
monkeypatch.setattr(os, "get_terminal_size", lambda fd=1: os.terminal_size((80, 24)))
111112

112113

114+
@pytest.fixture
115+
def running_pipe_process(monkeypatch: pytest.MonkeyPatch) -> None:
116+
"""Exercise real pipe I/O without the failed-start detection delay.
117+
118+
Successful-pipe tests need a running child, not a timed startup probe. Model
119+
that probe's timeout, but keep real unbounded waits so subprocess output and
120+
exit are still observed. Early-exit handling has its own deterministic test.
121+
"""
122+
wait = subprocess.Popen.wait
123+
124+
def wait_without_probe(process, timeout=None):
125+
if timeout is not None:
126+
raise subprocess.TimeoutExpired(process.args, timeout)
127+
return wait(process)
128+
129+
monkeypatch.setattr(subprocess.Popen, "wait", wait_without_probe)
130+
131+
113132
@pytest.fixture
114133
def base_app() -> cmd2.Cmd:
115134
return cmd2.Cmd(include_py=True, include_ipy=True)

‎tests/test_cmd2.py‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,7 @@ def test_disallow_redirection(redirection_app: RedirectionApp, capsys: pytest.Ca
843843
assert not os.path.exists(filename)
844844

845845

846-
def test_pipe_to_shell(redirection_app: RedirectionApp, capsys: pytest.CaptureFixture[str]) -> None:
846+
def test_pipe_to_shell(redirection_app: RedirectionApp, capsys: pytest.CaptureFixture[str], running_pipe_process) -> None:
847847
out, err = run_cmd(redirection_app, "print_output | sort")
848848

849849
# Verify print() went to sys.stdout
@@ -856,7 +856,7 @@ def test_pipe_to_shell(redirection_app: RedirectionApp, capsys: pytest.CaptureFi
856856
assert not err
857857

858858

859-
def test_pipe_to_shell_and_redirect(redirection_app) -> None:
859+
def test_pipe_to_shell_and_redirect(redirection_app, running_pipe_process) -> None:
860860
filename = "out.txt"
861861
out, err = run_cmd(redirection_app, f"print_output | sort > {filename}")
862862
assert not out
@@ -962,6 +962,9 @@ def test_base_timing(base_app) -> None:
962962

963963

964964
def test_base_debug(base_app) -> None:
965+
# Verify the debug toggle and real traceback, without syntax-highlighting the
966+
# entire cmd2 source file just to assert the traceback header.
967+
base_app.traceback_kwargs["suppress"] = [cmd2]
965968
# Purposely set the editor to None
966969
base_app.editor = None
967970

‎tests/test_suite_environment.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def test_redirection_to_a_file_uses_utf8(tmp_path) -> None:
6363
PASS_THROUGH = "import sys; sys.stdin.reconfigure(encoding='utf-8'); sys.stdout.write(sys.stdin.read())"
6464

6565

66-
def test_piping_uses_utf8(tmp_path) -> None:
66+
def test_piping_uses_utf8(tmp_path, running_pipe_process) -> None:
6767
"""The same applies to the pipe the subprocess reads from."""
6868
app = EncodingProbe(allow_cli_args=False)
6969
target = tmp_path / "piped.txt"

0 commit comments

Comments
 (0)