Skip to content

Commit a152c2c

Browse files
[8.2.x] Consider KeyboardInterrupt/SystemExit at collection time (#12282)
Co-authored-by: Anita Hammer <[email protected]>
1 parent 69c3bce commit a152c2c

File tree

4 files changed

+36
-1
lines changed

4 files changed

+36
-1
lines changed

AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Andrey Paramonov
3636
Andrzej Klajnert
3737
Andrzej Ostrowski
3838
Andy Freeland
39+
Anita Hammer
3940
Anthon van der Neut
4041
Anthony Shaw
4142
Anthony Sottile

changelog/12191.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Keyboard interrupts and system exits are now properly handled during the test collection.

src/_pytest/runner.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,9 @@ def collect() -> List[Union[Item, Collector]]:
388388

389389
return list(collector.collect())
390390

391-
call = CallInfo.from_call(collect, "collect")
391+
call = CallInfo.from_call(
392+
collect, "collect", reraise=(KeyboardInterrupt, SystemExit)
393+
)
392394
longrepr: Union[None, Tuple[str, int, str], str, TerminalRepr] = None
393395
if not call.excinfo:
394396
outcome: Literal["passed", "skipped", "failed"] = "passed"

testing/test_collection.py

+31
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import tempfile
88
import textwrap
99
from typing import List
10+
from typing import Type
1011

1112
from _pytest.assertion.util import running_on_ci
1213
from _pytest.config import ExitCode
@@ -1857,3 +1858,33 @@ def test_do_not_collect_symlink_siblings(
18571858
# Ensure we collect it only once if we pass the symlinked directory.
18581859
result = pytester.runpytest(symlink_path, "-sv")
18591860
result.assert_outcomes(passed=1)
1861+
1862+
1863+
@pytest.mark.parametrize(
1864+
"exception_class, msg",
1865+
[
1866+
(KeyboardInterrupt, "*!!! KeyboardInterrupt !!!*"),
1867+
(SystemExit, "INTERNALERROR> SystemExit"),
1868+
],
1869+
)
1870+
def test_respect_system_exceptions(
1871+
pytester: Pytester,
1872+
exception_class: Type[BaseException],
1873+
msg: str,
1874+
):
1875+
head = "Before exception"
1876+
tail = "After exception"
1877+
ensure_file(pytester.path / "test_eggs.py").write_text(
1878+
f"print('{head}')", encoding="UTF-8"
1879+
)
1880+
ensure_file(pytester.path / "test_ham.py").write_text(
1881+
f"raise {exception_class.__name__}()", encoding="UTF-8"
1882+
)
1883+
ensure_file(pytester.path / "test_spam.py").write_text(
1884+
f"print('{tail}')", encoding="UTF-8"
1885+
)
1886+
1887+
result = pytester.runpytest_subprocess("-s")
1888+
result.stdout.fnmatch_lines([f"*{head}*"])
1889+
result.stdout.fnmatch_lines([msg])
1890+
result.stdout.no_fnmatch_line(f"*{tail}*")

0 commit comments

Comments
 (0)