diff --git a/changelog/4599.feature.rst b/changelog/4599.feature.rst new file mode 100644 index 000000000..12ed20b23 --- /dev/null +++ b/changelog/4599.feature.rst @@ -0,0 +1,2 @@ +``pytest.importorskip`` now supports a ``reason`` parameter, which will be shown when the +requested module cannot be imported. diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index 714be3088..d27939e30 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -137,10 +137,15 @@ def xfail(reason=""): xfail.Exception = XFailed -def importorskip(modname, minversion=None): - """ return imported module if it has at least "minversion" as its - __version__ attribute. If no minversion is specified the a skip - is only triggered if the module can not be imported. +def importorskip(modname, minversion=None, reason=None): + """Imports and returns the requested module ``modname``, or skip the current test + if the module cannot be imported. + + :param str modname: the name of the module to import + :param str minversion: if given, the imported module ``__version__`` attribute must be + at least this minimal version, otherwise the test is still skipped. + :param str reason: if given, this reason is shown as the message when the module + cannot be imported. """ import warnings @@ -159,7 +164,9 @@ def importorskip(modname, minversion=None): # Do not raise chained exception here(#1485) should_skip = True if should_skip: - raise Skipped("could not import %r" % (modname,), allow_module_level=True) + if reason is None: + reason = "could not import %r" % (modname,) + raise Skipped(reason, allow_module_level=True) mod = sys.modules[modname] if minversion is None: return mod diff --git a/testing/test_runner.py b/testing/test_runner.py index ae129d06d..91f7d2700 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -738,6 +738,22 @@ def test_importorskip_module_level(testdir): result.stdout.fnmatch_lines(["*collected 0 items / 1 skipped*"]) +def test_importorskip_custom_reason(testdir): + """make sure custom reasons are used""" + testdir.makepyfile( + """ + import pytest + foobarbaz = pytest.importorskip("foobarbaz2", reason="just because") + + def test_foo(): + pass + """ + ) + result = testdir.runpytest("-ra") + result.stdout.fnmatch_lines(["*just because*"]) + result.stdout.fnmatch_lines(["*collected 0 items / 1 skipped*"]) + + def test_pytest_cmdline_main(testdir): p = testdir.makepyfile( """