diff --git a/changelog/5125.removal.rst b/changelog/5125.removal.rst new file mode 100644 index 00000000000..8f67c7399ae --- /dev/null +++ b/changelog/5125.removal.rst @@ -0,0 +1,5 @@ +``Session.exitcode`` values are now coded in ``pytest.ExitCode``, an ``IntEnum``. This makes the exit code available for consumer code and are more explicit other than just documentation. User defined exit codes are still valid, but should be used with caution. + +The team doesn't expect this change to break test suites or plugins in general, except in esoteric/specific scenarios. + +**pytest-xdist** users should upgrade to ``1.29.0`` or later, as ``pytest-xdist`` required a compatibility fix because of this change. diff --git a/doc/en/reference.rst b/doc/en/reference.rst index 0b168eb5442..3b1d3f2620d 100644 --- a/doc/en/reference.rst +++ b/doc/en/reference.rst @@ -727,6 +727,14 @@ ExceptionInfo .. autoclass:: _pytest._code.ExceptionInfo :members: + +pytest.ExitCode +~~~~~~~~~~~~~~~ + +.. autoclass:: _pytest.main.ExitCode + :members: + + FixtureDef ~~~~~~~~~~ diff --git a/doc/en/usage.rst b/doc/en/usage.rst index acf736f211e..ad7e2cdabc5 100644 --- a/doc/en/usage.rst +++ b/doc/en/usage.rst @@ -33,6 +33,8 @@ Running ``pytest`` can result in six different exit codes: :Exit code 4: pytest command line usage error :Exit code 5: No tests were collected +They are repressended by the :class:`_pytest.main.ExitCode` enum. + Getting help on version, option names, environment variables -------------------------------------------------------------- diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index c48688f3ae1..e6de86c3619 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -48,7 +48,7 @@ def main(args=None, plugins=None): :arg plugins: list of plugin objects to be auto-registered during initialization. """ - from _pytest.main import EXIT_USAGEERROR + from _pytest.main import ExitCode try: try: @@ -78,7 +78,7 @@ def main(args=None, plugins=None): tw = py.io.TerminalWriter(sys.stderr) for msg in e.args: tw.line("ERROR: {}\n".format(msg), red=True) - return EXIT_USAGEERROR + return ExitCode.USAGE_ERROR class cmdline: # compatibility namespace diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 735d60bd68e..e9b31bca7cf 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -1,4 +1,5 @@ """ core implementation of testing process: init, session, runtest loop. """ +import enum import fnmatch import functools import os @@ -18,13 +19,26 @@ from _pytest.outcomes import exit from _pytest.runner import collect_one_node -# exitcodes for the command line -EXIT_OK = 0 -EXIT_TESTSFAILED = 1 -EXIT_INTERRUPTED = 2 -EXIT_INTERNALERROR = 3 -EXIT_USAGEERROR = 4 -EXIT_NOTESTSCOLLECTED = 5 + +class ExitCode(enum.IntEnum): + """ + Encodes the valid exit codes by pytest. + + Currently users and plugins may supply other exit codes as well. + """ + + #: tests passed + OK = 0 + #: tests failed + TESTS_FAILED = 1 + #: pytest was interrupted + INTERRUPTED = 2 + #: an internal error got in the way + INTERNAL_ERROR = 3 + #: pytest was missused + USAGE_ERROR = 4 + #: pytest couldnt find tests + NO_TESTS_COLLECTED = 5 def pytest_addoption(parser): @@ -188,7 +202,7 @@ def pytest_configure(config): def wrap_session(config, doit): """Skeleton command line program""" session = Session(config) - session.exitstatus = EXIT_OK + session.exitstatus = ExitCode.OK initstate = 0 try: try: @@ -198,13 +212,13 @@ def wrap_session(config, doit): initstate = 2 session.exitstatus = doit(config, session) or 0 except UsageError: - session.exitstatus = EXIT_USAGEERROR + session.exitstatus = ExitCode.USAGE_ERROR raise except Failed: - session.exitstatus = EXIT_TESTSFAILED + session.exitstatus = ExitCode.TESTS_FAILED except (KeyboardInterrupt, exit.Exception): excinfo = _pytest._code.ExceptionInfo.from_current() - exitstatus = EXIT_INTERRUPTED + exitstatus = ExitCode.INTERRUPTED if isinstance(excinfo.value, exit.Exception): if excinfo.value.returncode is not None: exitstatus = excinfo.value.returncode @@ -217,7 +231,7 @@ def wrap_session(config, doit): except: # noqa excinfo = _pytest._code.ExceptionInfo.from_current() config.notify_exception(excinfo, config.option) - session.exitstatus = EXIT_INTERNALERROR + session.exitstatus = ExitCode.INTERNAL_ERROR if excinfo.errisinstance(SystemExit): sys.stderr.write("mainloop: caught unexpected SystemExit!\n") @@ -243,9 +257,9 @@ def _main(config, session): config.hook.pytest_runtestloop(session=session) if session.testsfailed: - return EXIT_TESTSFAILED + return ExitCode.TESTS_FAILED elif session.testscollected == 0: - return EXIT_NOTESTSCOLLECTED + return ExitCode.NO_TESTS_COLLECTED def pytest_collection(session): diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 4f0342ab5d4..1da5bd9ef9b 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -19,8 +19,7 @@ from _pytest.assertion.rewrite import AssertionRewritingHook from _pytest.capture import MultiCapture from _pytest.capture import SysCapture -from _pytest.main import EXIT_INTERRUPTED -from _pytest.main import EXIT_OK +from _pytest.main import ExitCode from _pytest.main import Session from _pytest.monkeypatch import MonkeyPatch from _pytest.pathlib import Path @@ -691,7 +690,7 @@ def getnode(self, config, arg): p = py.path.local(arg) config.hook.pytest_sessionstart(session=session) res = session.perform_collect([str(p)], genitems=False)[0] - config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK) + config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK) return res def getpathnode(self, path): @@ -708,11 +707,11 @@ def getpathnode(self, path): x = session.fspath.bestrelpath(path) config.hook.pytest_sessionstart(session=session) res = session.perform_collect([x], genitems=False)[0] - config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK) + config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK) return res def genitems(self, colitems): - """Generate all test items from a collection node. + """Generate all test items from a collection node.src/_pytest/main.py This recurses into the collection node and returns a list of all the test items contained within. @@ -841,7 +840,7 @@ class reprec: # typically we reraise keyboard interrupts from the child run # because it's our user requesting interruption of the testing - if ret == EXIT_INTERRUPTED and not no_reraise_ctrlc: + if ret == ExitCode.INTERRUPTED and not no_reraise_ctrlc: calls = reprec.getcalls("pytest_keyboard_interrupt") if calls and calls[-1].excinfo.type == KeyboardInterrupt: raise KeyboardInterrupt() diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 6f989030175..91e37385276 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -16,11 +16,7 @@ import pytest from _pytest import nodes -from _pytest.main import EXIT_INTERRUPTED -from _pytest.main import EXIT_NOTESTSCOLLECTED -from _pytest.main import EXIT_OK -from _pytest.main import EXIT_TESTSFAILED -from _pytest.main import EXIT_USAGEERROR +from _pytest.main import ExitCode REPORT_COLLECTING_RESOLUTION = 0.5 @@ -654,17 +650,17 @@ def pytest_sessionfinish(self, exitstatus): outcome.get_result() self._tw.line("") summary_exit_codes = ( - EXIT_OK, - EXIT_TESTSFAILED, - EXIT_INTERRUPTED, - EXIT_USAGEERROR, - EXIT_NOTESTSCOLLECTED, + ExitCode.OK, + ExitCode.TESTS_FAILED, + ExitCode.INTERRUPTED, + ExitCode.USAGE_ERROR, + ExitCode.NO_TESTS_COLLECTED, ) if exitstatus in summary_exit_codes: self.config.hook.pytest_terminal_summary( terminalreporter=self, exitstatus=exitstatus, config=self.config ) - if exitstatus == EXIT_INTERRUPTED: + if exitstatus == ExitCode.INTERRUPTED: self._report_keyboardinterrupt() del self._keyboardinterrupt_memo self.summary_stats() diff --git a/src/pytest.py b/src/pytest.py index a6376843d24..a3fa260845d 100644 --- a/src/pytest.py +++ b/src/pytest.py @@ -15,6 +15,7 @@ from _pytest.fixtures import fixture from _pytest.fixtures import yield_fixture from _pytest.freeze_support import freeze_includes +from _pytest.main import ExitCode from _pytest.main import Session from _pytest.mark import MARK_GEN as mark from _pytest.mark import param @@ -57,6 +58,7 @@ "Collector", "deprecated_call", "exit", + "ExitCode", "fail", "File", "fixture", diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index caa0d5191f2..60cc21c4a01 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -8,8 +8,7 @@ import py import pytest -from _pytest.main import EXIT_NOTESTSCOLLECTED -from _pytest.main import EXIT_USAGEERROR +from _pytest.main import ExitCode from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG @@ -24,7 +23,7 @@ class TestGeneralUsage: def test_config_error(self, testdir): testdir.copy_example("conftest_usageerror/conftest.py") result = testdir.runpytest(testdir.tmpdir) - assert result.ret == EXIT_USAGEERROR + assert result.ret == ExitCode.USAGE_ERROR result.stderr.fnmatch_lines(["*ERROR: hello"]) result.stdout.fnmatch_lines(["*pytest_unconfigure_called"]) @@ -83,7 +82,7 @@ def pytest_unconfigure(): """ ) result = testdir.runpytest("-s", "asd") - assert result.ret == 4 # EXIT_USAGEERROR + assert result.ret == ExitCode.USAGE_ERROR result.stderr.fnmatch_lines(["ERROR: file not found*asd"]) result.stdout.fnmatch_lines(["*---configure", "*---unconfigure"]) @@ -229,7 +228,7 @@ def pytest_collect_directory(): """ ) result = testdir.runpytest() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED result.stdout.fnmatch_lines(["*1 skip*"]) def test_issue88_initial_file_multinodes(self, testdir): @@ -247,7 +246,7 @@ def test_issue93_initialnode_importing_capturing(self, testdir): """ ) result = testdir.runpytest() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED assert "should not be seen" not in result.stdout.str() assert "stderr42" not in result.stderr.str() @@ -290,13 +289,13 @@ def test_issue109_sibling_conftests_not_loaded(self, testdir): sub2 = testdir.mkdir("sub2") sub1.join("conftest.py").write("assert 0") result = testdir.runpytest(sub2) - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED sub2.ensure("__init__.py") p = sub2.ensure("test_hello.py") result = testdir.runpytest(p) - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED result = testdir.runpytest(sub1) - assert result.ret == EXIT_USAGEERROR + assert result.ret == ExitCode.USAGE_ERROR def test_directory_skipped(self, testdir): testdir.makeconftest( @@ -308,7 +307,7 @@ def pytest_ignore_collect(): ) testdir.makepyfile("def test_hello(): pass") result = testdir.runpytest() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED result.stdout.fnmatch_lines(["*1 skipped*"]) def test_multiple_items_per_collector_byid(self, testdir): @@ -410,10 +409,10 @@ def test_a(): def test_report_all_failed_collections_initargs(self, testdir): testdir.makeconftest( """ - from _pytest.main import EXIT_USAGEERROR + from _pytest.main import ExitCode def pytest_sessionfinish(exitstatus): - assert exitstatus == EXIT_USAGEERROR + assert exitstatus == ExitCode.USAGE_ERROR print("pytest_sessionfinish_called") """ ) @@ -421,7 +420,7 @@ def pytest_sessionfinish(exitstatus): result = testdir.runpytest("test_a.py::a", "test_b.py::b") result.stderr.fnmatch_lines(["*ERROR*test_a.py::a*", "*ERROR*test_b.py::b*"]) result.stdout.fnmatch_lines(["pytest_sessionfinish_called"]) - assert result.ret == EXIT_USAGEERROR + assert result.ret == ExitCode.USAGE_ERROR @pytest.mark.usefixtures("recwarn") def test_namespace_import_doesnt_confuse_import_hook(self, testdir): @@ -612,7 +611,7 @@ def test_invoke_with_invalid_type(self, capsys): def test_invoke_with_path(self, tmpdir, capsys): retcode = pytest.main(tmpdir) - assert retcode == EXIT_NOTESTSCOLLECTED + assert retcode == ExitCode.NO_TESTS_COLLECTED out, err = capsys.readouterr() def test_invoke_plugin_api(self, testdir, capsys): @@ -1160,7 +1159,7 @@ def test_fixture_mock_integration(testdir): def test_usage_error_code(testdir): result = testdir.runpytest("-unknown-option-") - assert result.ret == EXIT_USAGEERROR + assert result.ret == ExitCode.USAGE_ERROR @pytest.mark.filterwarnings("default") diff --git a/testing/python/collect.py b/testing/python/collect.py index d648452fd78..c2b09aeb86a 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -4,7 +4,7 @@ import _pytest._code import pytest -from _pytest.main import EXIT_NOTESTSCOLLECTED +from _pytest.main import ExitCode from _pytest.nodes import Collector @@ -246,7 +246,7 @@ def prop(self): """ ) result = testdir.runpytest() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED class TestFunction: @@ -1140,7 +1140,7 @@ class Test(object): ) result = testdir.runpytest() assert "TypeError" not in result.stdout.str() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED def test_collect_functools_partial(testdir): diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 61c5b93834f..0e6f42239f2 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -15,7 +15,7 @@ from _pytest.assertion.rewrite import AssertionRewritingHook from _pytest.assertion.rewrite import PYTEST_TAG from _pytest.assertion.rewrite import rewrite_asserts -from _pytest.main import EXIT_NOTESTSCOLLECTED +from _pytest.main import ExitCode def setup_module(mod): @@ -692,7 +692,7 @@ def test_zipfile(self, testdir): import test_gum.test_lizard""" % (z_fn,) ) - assert testdir.runpytest().ret == EXIT_NOTESTSCOLLECTED + assert testdir.runpytest().ret == ExitCode.NO_TESTS_COLLECTED def test_readonly(self, testdir): sub = testdir.mkdir("testing") @@ -792,7 +792,7 @@ def test_package_without__init__py(self, testdir): pkg = testdir.mkdir("a_package_without_init_py") pkg.join("module.py").ensure() testdir.makepyfile("import a_package_without_init_py.module") - assert testdir.runpytest().ret == EXIT_NOTESTSCOLLECTED + assert testdir.runpytest().ret == ExitCode.NO_TESTS_COLLECTED def test_rewrite_warning(self, testdir): testdir.makeconftest( diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index a2e701740a0..cbba27e5f5d 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -6,7 +6,7 @@ import py import pytest -from _pytest.main import EXIT_NOTESTSCOLLECTED +from _pytest.main import ExitCode pytest_plugins = ("pytester",) @@ -757,7 +757,7 @@ def test_2(): "* 2 deselected in *", ] ) - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED def test_lastfailed_no_failures_behavior_empty_cache(self, testdir): testdir.makepyfile( diff --git a/testing/test_capture.py b/testing/test_capture.py index a85025c27d2..8d1d33bc736 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -12,7 +12,7 @@ import pytest from _pytest import capture from _pytest.capture import CaptureManager -from _pytest.main import EXIT_NOTESTSCOLLECTED +from _pytest.main import ExitCode # note: py.io capture tests where copied from # pylib 1.4.20.dev2 (rev 13d9af95547e) @@ -361,7 +361,7 @@ def test_conftestlogging_is_shown(self, testdir): ) # make sure that logging is still captured in tests result = testdir.runpytest_subprocess("-s", "-p", "no:capturelog") - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED result.stderr.fnmatch_lines(["WARNING*hello435*"]) assert "operation on closed file" not in result.stderr.str() diff --git a/testing/test_collection.py b/testing/test_collection.py index c938a915d1d..864125c40af 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -7,8 +7,7 @@ import pytest from _pytest.main import _in_venv -from _pytest.main import EXIT_INTERRUPTED -from _pytest.main import EXIT_NOTESTSCOLLECTED +from _pytest.main import ExitCode from _pytest.main import Session @@ -347,7 +346,7 @@ def pytest_ignore_collect(path, config): assert result.ret == 0 result.stdout.fnmatch_lines(["*1 passed*"]) result = testdir.runpytest() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED result.stdout.fnmatch_lines(["*collected 0 items*"]) def test_collectignore_exclude_on_option(self, testdir): @@ -364,7 +363,7 @@ def pytest_configure(config): testdir.mkdir("hello") testdir.makepyfile(test_world="def test_hello(): pass") result = testdir.runpytest() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED assert "passed" not in result.stdout.str() result = testdir.runpytest("--XX") assert result.ret == 0 @@ -384,7 +383,7 @@ def pytest_configure(config): testdir.makepyfile(test_world="def test_hello(): pass") testdir.makepyfile(test_welt="def test_hallo(): pass") result = testdir.runpytest() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED result.stdout.fnmatch_lines(["*collected 0 items*"]) result = testdir.runpytest("--XX") assert result.ret == 0 @@ -1172,7 +1171,7 @@ def test_collectignore_via_conftest(testdir, monkeypatch): ignore_me.ensure("conftest.py").write("assert 0, 'should_not_be_called'") result = testdir.runpytest() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED def test_collect_pkg_init_and_file_in_args(testdir): @@ -1234,7 +1233,7 @@ def test_collect_sub_with_symlinks(use_pkg, testdir): def test_collector_respects_tbstyle(testdir): p1 = testdir.makepyfile("assert 0") result = testdir.runpytest(p1, "--tb=native") - assert result.ret == EXIT_INTERRUPTED + assert result.ret == ExitCode.INTERRUPTED result.stdout.fnmatch_lines( [ "*_ ERROR collecting test_collector_respects_tbstyle.py _*", diff --git a/testing/test_config.py b/testing/test_config.py index c3b027ab901..b9fc388d236 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -10,10 +10,7 @@ from _pytest.config.findpaths import determine_setup from _pytest.config.findpaths import get_common_ancestor from _pytest.config.findpaths import getcfg -from _pytest.main import EXIT_NOTESTSCOLLECTED -from _pytest.main import EXIT_OK -from _pytest.main import EXIT_TESTSFAILED -from _pytest.main import EXIT_USAGEERROR +from _pytest.main import ExitCode class TestParseIni: @@ -189,7 +186,7 @@ def test_absolute_win32_path(self, testdir): temp_ini_file = normpath(str(temp_ini_file)) ret = pytest.main(["-c", temp_ini_file]) - assert ret == _pytest.main.EXIT_OK + assert ret == ExitCode.OK class TestConfigAPI: @@ -726,7 +723,7 @@ def test_consider_args_after_options_for_rootdir(testdir, args): @pytest.mark.skipif("sys.platform == 'win32'") def test_toolongargs_issue224(testdir): result = testdir.runpytest("-m", "hello" * 500) - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED def test_config_in_subdirectory_colon_command_line_issue2148(testdir): @@ -1086,7 +1083,7 @@ def test_addopts_from_ini_not_concatenated(self, testdir): % (testdir.request.config._parser.optparser.prog,) ] ) - assert result.ret == _pytest.main.EXIT_USAGEERROR + assert result.ret == _pytest.main.ExitCode.USAGE_ERROR def test_override_ini_does_not_contain_paths(self, _config_for_test, _sys_snapshot): """Check that -o no longer swallows all options after it (#3103)""" @@ -1175,13 +1172,13 @@ def pytest_addoption(parser): ) # Does not display full/default help. assert "to see available markers type: pytest --markers" not in result.stdout.lines - assert result.ret == EXIT_USAGEERROR + assert result.ret == ExitCode.USAGE_ERROR result = testdir.runpytest("--version") result.stderr.fnmatch_lines( ["*pytest*{}*imported from*".format(pytest.__version__)] ) - assert result.ret == EXIT_USAGEERROR + assert result.ret == ExitCode.USAGE_ERROR def test_config_does_not_load_blocked_plugin_from_args(testdir): @@ -1189,11 +1186,11 @@ def test_config_does_not_load_blocked_plugin_from_args(testdir): p = testdir.makepyfile("def test(capfd): pass") result = testdir.runpytest(str(p), "-pno:capture") result.stdout.fnmatch_lines(["E fixture 'capfd' not found"]) - assert result.ret == EXIT_TESTSFAILED + assert result.ret == ExitCode.TESTS_FAILED result = testdir.runpytest(str(p), "-pno:capture", "-s") result.stderr.fnmatch_lines(["*: error: unrecognized arguments: -s"]) - assert result.ret == EXIT_USAGEERROR + assert result.ret == ExitCode.USAGE_ERROR @pytest.mark.parametrize( @@ -1219,7 +1216,7 @@ def test_config_blocked_default_plugins(testdir, plugin): result = testdir.runpytest(str(p), "-pno:%s" % plugin) if plugin == "python": - assert result.ret == EXIT_USAGEERROR + assert result.ret == ExitCode.USAGE_ERROR result.stderr.fnmatch_lines( [ "ERROR: not found: */test_config_blocked_default_plugins.py", @@ -1228,13 +1225,13 @@ def test_config_blocked_default_plugins(testdir, plugin): ) return - assert result.ret == EXIT_OK + assert result.ret == ExitCode.OK if plugin != "terminal": result.stdout.fnmatch_lines(["* 1 passed in *"]) p = testdir.makepyfile("def test(): assert 0") result = testdir.runpytest(str(p), "-pno:%s" % plugin) - assert result.ret == EXIT_TESTSFAILED + assert result.ret == ExitCode.TESTS_FAILED if plugin != "terminal": result.stdout.fnmatch_lines(["* 1 failed in *"]) else: diff --git a/testing/test_conftest.py b/testing/test_conftest.py index f29531eb7bd..447416f1076 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -4,9 +4,7 @@ import pytest from _pytest.config import PytestPluginManager -from _pytest.main import EXIT_NOTESTSCOLLECTED -from _pytest.main import EXIT_OK -from _pytest.main import EXIT_USAGEERROR +from _pytest.main import ExitCode def ConftestWithSetinitial(path): @@ -223,11 +221,11 @@ def fixture(): "PASSED", ] ) - assert result.ret == EXIT_OK + assert result.ret == ExitCode.OK # Should not cause "ValueError: Plugin already registered" (#4174). result = testdir.runpytest("-vs", "symlink") - assert result.ret == EXIT_OK + assert result.ret == ExitCode.OK realtests.ensure("__init__.py") result = testdir.runpytest("-vs", "symlinktests/test_foo.py::test1") @@ -238,7 +236,7 @@ def fixture(): "PASSED", ] ) - assert result.ret == EXIT_OK + assert result.ret == ExitCode.OK @pytest.mark.skipif( @@ -274,16 +272,16 @@ def fixture(): build.chdir() result = testdir.runpytest("-vs", "app/test_foo.py") result.stdout.fnmatch_lines(["*conftest_loaded*", "PASSED"]) - assert result.ret == EXIT_OK + assert result.ret == ExitCode.OK def test_no_conftest(testdir): testdir.makeconftest("assert 0") result = testdir.runpytest("--noconftest") - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED result = testdir.runpytest() - assert result.ret == EXIT_USAGEERROR + assert result.ret == ExitCode.USAGE_ERROR def test_conftest_existing_resultlog(testdir): diff --git a/testing/test_helpconfig.py b/testing/test_helpconfig.py index ec061cad99d..962750f7b3a 100644 --- a/testing/test_helpconfig.py +++ b/testing/test_helpconfig.py @@ -1,5 +1,5 @@ import pytest -from _pytest.main import EXIT_NOTESTSCOLLECTED +from _pytest.main import ExitCode def test_version(testdir, pytestconfig): @@ -49,7 +49,7 @@ def pytest_hello(xyz): """ ) result = testdir.runpytest() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED def test_traceconfig(testdir): @@ -59,7 +59,7 @@ def test_traceconfig(testdir): def test_debug(testdir, monkeypatch): result = testdir.runpytest_subprocess("--debug") - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED p = testdir.tmpdir.join("pytestdebug.log") assert "pytest_sessionstart" in p.read() @@ -67,7 +67,7 @@ def test_debug(testdir, monkeypatch): def test_PYTEST_DEBUG(testdir, monkeypatch): monkeypatch.setenv("PYTEST_DEBUG", "1") result = testdir.runpytest_subprocess() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED result.stderr.fnmatch_lines( ["*pytest_plugin_registered*", "*manager*PluginManager*"] ) diff --git a/testing/test_mark.py b/testing/test_mark.py index 8d97f8b4ef5..c22e9dbb5de 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -3,7 +3,7 @@ from unittest import mock import pytest -from _pytest.main import EXIT_INTERRUPTED +from _pytest.main import ExitCode from _pytest.mark import EMPTY_PARAMETERSET_OPTION from _pytest.mark import MarkGenerator as Mark from _pytest.nodes import Collector @@ -903,7 +903,7 @@ def test(): "*= 1 error in *", ] ) - assert result.ret == EXIT_INTERRUPTED + assert result.ret == ExitCode.INTERRUPTED def test_parameterset_for_parametrize_bad_markname(testdir): diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index 8afb37fa149..97f220ca553 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -5,7 +5,7 @@ import pytest from _pytest.config import PytestPluginManager from _pytest.config.exceptions import UsageError -from _pytest.main import EXIT_NOTESTSCOLLECTED +from _pytest.main import ExitCode from _pytest.main import Session @@ -227,7 +227,7 @@ def test_plugin_skip(self, testdir, monkeypatch): p.copy(p.dirpath("skipping2.py")) monkeypatch.setenv("PYTEST_PLUGINS", "skipping2") result = testdir.runpytest("-rw", "-p", "skipping1", syspathinsert=True) - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED result.stdout.fnmatch_lines( ["*skipped plugin*skipping1*hello*", "*skipped plugin*skipping2*hello*"] ) diff --git a/testing/test_pytester.py b/testing/test_pytester.py index ca12672f598..37b63f31afe 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -8,9 +8,7 @@ import _pytest.pytester as pytester import pytest from _pytest.config import PytestPluginManager -from _pytest.main import EXIT_NOTESTSCOLLECTED -from _pytest.main import EXIT_OK -from _pytest.main import EXIT_TESTSFAILED +from _pytest.main import ExitCode from _pytest.pytester import CwdSnapshot from _pytest.pytester import HookRecorder from _pytest.pytester import LineMatcher @@ -206,11 +204,11 @@ class TestInlineRunModulesCleanup: def test_inline_run_test_module_not_cleaned_up(self, testdir): test_mod = testdir.makepyfile("def test_foo(): assert True") result = testdir.inline_run(str(test_mod)) - assert result.ret == EXIT_OK + assert result.ret == ExitCode.OK # rewrite module, now test should fail if module was re-imported test_mod.write("def test_foo(): assert False") result2 = testdir.inline_run(str(test_mod)) - assert result2.ret == EXIT_TESTSFAILED + assert result2.ret == ExitCode.TESTS_FAILED def spy_factory(self): class SysModulesSnapshotSpy: @@ -411,12 +409,12 @@ def test_testdir_subprocess(testdir): def test_unicode_args(testdir): result = testdir.runpytest("-k", "💩") - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED def test_testdir_run_no_timeout(testdir): testfile = testdir.makepyfile("def test_no_timeout(): pass") - assert testdir.runpytest_subprocess(testfile).ret == EXIT_OK + assert testdir.runpytest_subprocess(testfile).ret == ExitCode.OK def test_testdir_run_with_timeout(testdir): @@ -429,7 +427,7 @@ def test_testdir_run_with_timeout(testdir): end = time.time() duration = end - start - assert result.ret == EXIT_OK + assert result.ret == ExitCode.OK assert duration < timeout diff --git a/testing/test_runner.py b/testing/test_runner.py index 13f722036dc..15180c07156 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -653,7 +653,7 @@ def test_hello(): def test_pytest_no_tests_collected_exit_status(testdir): result = testdir.runpytest() result.stdout.fnmatch_lines(["*collected 0 items*"]) - assert result.ret == main.EXIT_NOTESTSCOLLECTED + assert result.ret == main.ExitCode.NO_TESTS_COLLECTED testdir.makepyfile( test_foo=""" @@ -664,12 +664,12 @@ def test_foo(): result = testdir.runpytest() result.stdout.fnmatch_lines(["*collected 1 item*"]) result.stdout.fnmatch_lines(["*1 passed*"]) - assert result.ret == main.EXIT_OK + assert result.ret == main.ExitCode.OK result = testdir.runpytest("-k nonmatch") result.stdout.fnmatch_lines(["*collected 1 item*"]) result.stdout.fnmatch_lines(["*1 deselected*"]) - assert result.ret == main.EXIT_NOTESTSCOLLECTED + assert result.ret == main.ExitCode.NO_TESTS_COLLECTED def test_exception_printing_skip(): diff --git a/testing/test_session.py b/testing/test_session.py index 1a0ae808076..dbe0573760b 100644 --- a/testing/test_session.py +++ b/testing/test_session.py @@ -1,5 +1,5 @@ import pytest -from _pytest.main import EXIT_NOTESTSCOLLECTED +from _pytest.main import ExitCode class SessionTests: @@ -330,7 +330,7 @@ def pytest_sessionfinish(): """ ) res = testdir.runpytest("--collect-only") - assert res.ret == EXIT_NOTESTSCOLLECTED + assert res.ret == ExitCode.NO_TESTS_COLLECTED @pytest.mark.parametrize("path", ["root", "{relative}/root", "{environment}/root"]) diff --git a/testing/test_terminal.py b/testing/test_terminal.py index cc2c474ab45..bf029fbc533 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -10,7 +10,7 @@ import py import pytest -from _pytest.main import EXIT_NOTESTSCOLLECTED +from _pytest.main import ExitCode from _pytest.reports import BaseReport from _pytest.terminal import _folded_skips from _pytest.terminal import _get_line_with_reprcrash_message @@ -937,7 +937,7 @@ def test_opt(arg): def test_traceconfig(testdir, monkeypatch): result = testdir.runpytest("--traceconfig") result.stdout.fnmatch_lines(["*active plugins*"]) - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED class TestGenericReporting: diff --git a/testing/test_unittest.py b/testing/test_unittest.py index adcc232fd98..2467ddd39db 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -1,7 +1,7 @@ import gc import pytest -from _pytest.main import EXIT_NOTESTSCOLLECTED +from _pytest.main import ExitCode def test_simple_unittest(testdir): @@ -55,7 +55,7 @@ def __getattr__(self, tag): """ ) result = testdir.runpytest(testpath) - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED def test_setup(testdir): @@ -704,7 +704,7 @@ class Test(unittest.TestCase): ) result = testdir.runpytest() assert "TypeError" not in result.stdout.str() - assert result.ret == EXIT_NOTESTSCOLLECTED + assert result.ret == ExitCode.NO_TESTS_COLLECTED def test_unittest_typerror_traceback(testdir):