summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnita Hammer <166057949+anitahammer@users.noreply.github.com>2024-05-02 12:59:09 +0100
committerGitHub <noreply@github.com>2024-05-02 11:59:09 +0000
commit97610067acf220b13cc4c6fca34e5aac4834b04d (patch)
treed89a2bac9c96e0179794711233d7a3bb735c8403
parent4c5298c3954efa71436364efaf531d3851a6aeb4 (diff)
downloadpytest-upstream-main.tar.gz
Handle KeyboardInterrupt and SystemExit at collection time (#12191)upstream-main
-rw-r--r--AUTHORS1
-rw-r--r--changelog/12191.bugfix.rst1
-rw-r--r--src/_pytest/runner.py4
-rw-r--r--testing/test_collection.py31
4 files changed, 36 insertions, 1 deletions
diff --git a/AUTHORS b/AUTHORS
index 4f61c0591..4619cf1bc 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -36,6 +36,7 @@ Andrey Paramonov
Andrzej Klajnert
Andrzej Ostrowski
Andy Freeland
+Anita Hammer
Anthon van der Neut
Anthony Shaw
Anthony Sottile
diff --git a/changelog/12191.bugfix.rst b/changelog/12191.bugfix.rst
new file mode 100644
index 000000000..5102d4698
--- /dev/null
+++ b/changelog/12191.bugfix.rst
@@ -0,0 +1 @@
+Keyboard interrupts and system exits are now properly handled during the test collection.
diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py
index dfefa73b7..e5af60e38 100644
--- a/src/_pytest/runner.py
+++ b/src/_pytest/runner.py
@@ -393,7 +393,9 @@ def pytest_make_collect_report(collector: Collector) -> CollectReport:
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"
diff --git a/testing/test_collection.py b/testing/test_collection.py
index 9caca622c..995e2999b 100644
--- a/testing/test_collection.py
+++ b/testing/test_collection.py
@@ -7,6 +7,7 @@ import sys
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
@@ -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}*")