Skip to content

Add returncode argument to pytest.exit #4145

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Oct 15, 2018
1 change: 1 addition & 0 deletions changelog/4098.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add returncode argument to pytest.exit() to exit pytest with a specific return code.
7 changes: 5 additions & 2 deletions src/_pytest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,13 @@ def wrap_session(config, doit):
session.exitstatus = EXIT_TESTSFAILED
except KeyboardInterrupt:
excinfo = _pytest._code.ExceptionInfo()
if initstate < 2 and isinstance(excinfo.value, exit.Exception):
exitstatus = EXIT_INTERRUPTED
if initstate <= 2 and isinstance(excinfo.value, exit.Exception):
sys.stderr.write("{}: {}\n".format(excinfo.typename, excinfo.value.msg))
if excinfo.value.returncode is not None:
exitstatus = excinfo.value.returncode
config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
session.exitstatus = EXIT_INTERRUPTED
session.exitstatus = exitstatus
except: # noqa
excinfo = _pytest._code.ExceptionInfo()
config.notify_exception(excinfo, config.option)
Expand Down
14 changes: 10 additions & 4 deletions src/_pytest/outcomes.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,24 @@ class Failed(OutcomeException):
class Exit(KeyboardInterrupt):
""" raised for immediate program exits (no tracebacks/summaries)"""

def __init__(self, msg="unknown reason"):
def __init__(self, msg="unknown reason", returncode=None):
self.msg = msg
self.returncode = returncode
KeyboardInterrupt.__init__(self, msg)


# exposed helper methods


def exit(msg):
""" exit testing process as if KeyboardInterrupt was triggered. """
def exit(msg, returncode=None):
"""
Exit testing process as if KeyboardInterrupt was triggered.

:param str msg: message to display upon exit.
:param int returncode: return code to be used when exiting pytest.
"""
__tracebackhide__ = True
raise Exit(msg)
raise Exit(msg, returncode)


exit.Exception = Exit
Expand Down
12 changes: 12 additions & 0 deletions testing/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,18 @@ def pytest_configure(config):
result.stderr.fnmatch_lines(["Exit: oh noes"])


def test_pytest_exit_returncode(testdir):
testdir.makepyfile(
"""
import pytest
def test_foo():
pytest.exit("some exit msg", 99)
"""
)
result = testdir.runpytest()
assert result.ret == 99


def test_pytest_fail_notrace_runtest(testdir):
"""Test pytest.fail(..., pytrace=False) does not show tracebacks during test run."""
testdir.makepyfile(
Expand Down