Skip to content

Commit

Permalink
Handle KeyboardInterrupt and SystemExit at collection time (#12191)
Browse files Browse the repository at this point in the history
  • Loading branch information
anitahammer committed May 2, 2024
1 parent 4c5298c commit 9761006
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 1 deletion.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Andrey Paramonov
Andrzej Klajnert
Andrzej Ostrowski
Andy Freeland
Anita Hammer
Anthon van der Neut
Anthony Shaw
Anthony Sottile
Expand Down
1 change: 1 addition & 0 deletions changelog/12191.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Keyboard interrupts and system exits are now properly handled during the test collection.
4 changes: 3 additions & 1 deletion src/_pytest/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,9 @@ def collect() -> List[Union[Item, Collector]]:

return list(collector.collect())

call = CallInfo.from_call(collect, "collect")
call = CallInfo.from_call(
collect, "collect", reraise=(KeyboardInterrupt, SystemExit)
)
longrepr: Union[None, Tuple[str, int, str], str, TerminalRepr] = None
if not call.excinfo:
outcome: Literal["passed", "skipped", "failed"] = "passed"
Expand Down
31 changes: 31 additions & 0 deletions testing/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import tempfile
import textwrap
from typing import List
from typing import Type

from _pytest.assertion.util import running_on_ci
from _pytest.config import ExitCode
Expand Down Expand Up @@ -1856,3 +1857,33 @@ def test_do_not_collect_symlink_siblings(
# Ensure we collect it only once if we pass the symlinked directory.
result = pytester.runpytest(symlink_path, "-sv")
result.assert_outcomes(passed=1)


@pytest.mark.parametrize(
"exception_class, msg",
[
(KeyboardInterrupt, "*!!! KeyboardInterrupt !!!*"),
(SystemExit, "INTERNALERROR> SystemExit"),
],
)
def test_respect_system_exceptions(
pytester: Pytester,
exception_class: Type[BaseException],
msg: str,
):
head = "Before exception"
tail = "After exception"
ensure_file(pytester.path / "test_eggs.py").write_text(
f"print('{head}')", encoding="UTF-8"
)
ensure_file(pytester.path / "test_ham.py").write_text(
f"raise {exception_class.__name__}()", encoding="UTF-8"
)
ensure_file(pytester.path / "test_spam.py").write_text(
f"print('{tail}')", encoding="UTF-8"
)

result = pytester.runpytest_subprocess("-s")
result.stdout.fnmatch_lines([f"*{head}*"])
result.stdout.fnmatch_lines([msg])
result.stdout.no_fnmatch_line(f"*{tail}*")

0 comments on commit 9761006

Please sign in to comment.