From 79d33530812748482726a82a45b0e2754928c756 Mon Sep 17 00:00:00 2001 From: "George Y. Kussumoto" Date: Sun, 1 Oct 2017 18:38:29 -0300 Subject: [PATCH 1/8] Add allow_module_level kwarg to skip helper --- _pytest/outcomes.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/_pytest/outcomes.py b/_pytest/outcomes.py index ff5ef756d..75b0250f4 100644 --- a/_pytest/outcomes.py +++ b/_pytest/outcomes.py @@ -62,14 +62,21 @@ def exit(msg): exit.Exception = Exit -def skip(msg=""): +def skip(msg="", **kwargs): """ skip an executing test with the given message. Note: it's usually better to use the pytest.mark.skipif marker to declare a test to be skipped under certain conditions like mismatching platforms or dependencies. See the pytest_skipping plugin for details. + + :kwarg bool allow_module_level: allows this function to be called at + module level, skipping the rest of the module. Default to False. """ __tracebackhide__ = True - raise Skipped(msg=msg) + allow_module_level = kwargs.pop('allow_module_level', False) + if kwargs: + keys = [k for k in kwargs.keys()] + raise TypeError('unexpected keyworkd arguments: {}'.format(keys)) + raise Skipped(msg=msg, allow_module_level=allow_module_level) skip.Exception = Skipped From 06307be15d2db8d327c5f6f82d07aa590b760472 Mon Sep 17 00:00:00 2001 From: "George Y. Kussumoto" Date: Sun, 1 Oct 2017 18:39:14 -0300 Subject: [PATCH 2/8] Add initial tests using skip with allow_module_level kwarg --- testing/test_skipping.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 1fbb9ed0f..23c4c37ce 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -1005,6 +1005,40 @@ def test_module_level_skip_error(testdir): ) +def test_module_level_skip_with_allow_module_level(testdir): + """ + Verify that using pytest.skip(allow_module_level=True) is allowed + """ + testdir.makepyfile(""" + import pytest + pytest.skip("skip_module_level", allow_module_level=True) + + def test_func(): + assert 0 + """) + result = testdir.runpytest("-rxs") + result.stdout.fnmatch_lines( + "*SKIP*skip_module_level" + ) + + +def test_invalid_skip_keyword_parameter(testdir): + """ + Verify that using pytest.skip() with unknown parameter raises an error + """ + testdir.makepyfile(""" + import pytest + pytest.skip("skip_module_level", unknown=1) + + def test_func(): + assert 0 + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines( + "*TypeError:*['unknown']*" + ) + + def test_mark_xfail_item(testdir): # Ensure pytest.mark.xfail works with non-Python Item testdir.makeconftest(""" From e4a6e52b81c96bbeab2ff5506994722408622fd1 Mon Sep 17 00:00:00 2001 From: "George Y. Kussumoto" Date: Sun, 1 Oct 2017 18:40:19 -0300 Subject: [PATCH 3/8] Update skipping documentation to include usage of allow_module_level kwarg --- doc/en/skipping.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index 630f73422..e6f1bc3c5 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -54,6 +54,15 @@ by calling the ``pytest.skip(reason)`` function: if not valid_config(): pytest.skip("unsupported configuration") +It is also possible to skip the whole module using +``pytest.skip(reason, allow_module_level=True)`` at the module level: + + +.. code-block:: python + + if not enabled_platform_edge_cases(): + pytest.skip("unsupported platform", allow_module_level=True) + The imperative method is useful when it is not possible to evaluate the skip condition during import time. From c1aa63c0bbfe9b0b0613617b2c98941ff487cd03 Mon Sep 17 00:00:00 2001 From: "George Y. Kussumoto" Date: Mon, 2 Oct 2017 21:24:52 -0300 Subject: [PATCH 4/8] Fix docstring alignment and typos --- _pytest/outcomes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_pytest/outcomes.py b/_pytest/outcomes.py index 75b0250f4..7f0c18fa6 100644 --- a/_pytest/outcomes.py +++ b/_pytest/outcomes.py @@ -69,13 +69,13 @@ def skip(msg="", **kwargs): dependencies. See the pytest_skipping plugin for details. :kwarg bool allow_module_level: allows this function to be called at - module level, skipping the rest of the module. Default to False. + module level, skipping the rest of the module. Default to False. """ __tracebackhide__ = True allow_module_level = kwargs.pop('allow_module_level', False) if kwargs: keys = [k for k in kwargs.keys()] - raise TypeError('unexpected keyworkd arguments: {}'.format(keys)) + raise TypeError('unexpected keyword arguments: {0}'.format(keys)) raise Skipped(msg=msg, allow_module_level=allow_module_level) From 59f66933cd9468eec3dc67714f1b686f8dfb1c39 Mon Sep 17 00:00:00 2001 From: "George Y. Kussumoto" Date: Mon, 2 Oct 2017 21:26:00 -0300 Subject: [PATCH 5/8] Update documentation example of pytest.skip(allow_module_level=True) --- doc/en/skipping.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index e6f1bc3c5..2c91bab71 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -57,11 +57,12 @@ by calling the ``pytest.skip(reason)`` function: It is also possible to skip the whole module using ``pytest.skip(reason, allow_module_level=True)`` at the module level: - .. code-block:: python - if not enabled_platform_edge_cases(): - pytest.skip("unsupported platform", allow_module_level=True) + import pytest + + if not pytest.config.getoption("--custom-flag"): + pytest.skip("--custom-flag is missing, skipping tests", allow_module_level=True) The imperative method is useful when it is not possible to evaluate the skip condition during import time. From 9824499396a16cea957f1cd87c2c245b1cd68d8a Mon Sep 17 00:00:00 2001 From: "George Y. Kussumoto" Date: Mon, 2 Oct 2017 21:26:29 -0300 Subject: [PATCH 6/8] Add 2808.feature changelog entry --- changelog/2808.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/2808.feature diff --git a/changelog/2808.feature b/changelog/2808.feature new file mode 100644 index 000000000..26245f047 --- /dev/null +++ b/changelog/2808.feature @@ -0,0 +1 @@ +Add ``allow_module_level`` kwarg to ``pytest.skip()``, enabling to skip the whole module. From 03ce0adb79b012a6a34adb2d2fe6a6d9ba9b6fb2 Mon Sep 17 00:00:00 2001 From: "George Y. Kussumoto" Date: Wed, 4 Oct 2017 19:18:55 -0300 Subject: [PATCH 7/8] Fix: handle CollectReport in folded_skips function --- _pytest/skipping.py | 3 ++- testing/test_skipping.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index ef9f601ca..0fe602972 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -349,7 +349,8 @@ def folded_skips(skipped): # folding reports with global pytestmark variable # this is workaround, because for now we cannot identify the scope of a skip marker # TODO: revisit after marks scope would be fixed - if event.when == 'setup' and 'skip' in keywords and 'pytestmark' not in keywords: + when = getattr(event, 'when', None) + if when == 'setup' and 'skip' in keywords and 'pytestmark' not in keywords: key = (key[0], None, key[2], ) d.setdefault(key, []).append(event) l = [] diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 23c4c37ce..ae334e7cd 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -663,7 +663,7 @@ def test_skipif_class(testdir): def test_skip_reasons_folding(): - path = 'xyz' + path = "xyz" lineno = 3 message = "justso" longrepr = (path, lineno, message) @@ -680,10 +680,15 @@ def test_skip_reasons_folding(): ev2.longrepr = longrepr ev2.skipped = True - l = folded_skips([ev1, ev2]) + # ev3 might be a collection report + ev3 = X() + ev3.longrepr = longrepr + ev3.skipped = True + + l = folded_skips([ev1, ev2, ev3]) assert len(l) == 1 num, fspath, lineno, reason = l[0] - assert num == 2 + assert num == 3 assert fspath == path assert lineno == lineno assert reason == message From 0668a6c6d3aee3d52239165fd6f7f8a2bb5d6f9d Mon Sep 17 00:00:00 2001 From: "George Y. Kussumoto" Date: Wed, 4 Oct 2017 22:14:29 -0300 Subject: [PATCH 8/8] Add myself to authors file --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index cf31e0389..0fb9c7e04 100644 --- a/AUTHORS +++ b/AUTHORS @@ -64,6 +64,7 @@ Feng Ma Florian Bruhin Floris Bruynooghe Gabriel Reis +George Kussumoto Georgy Dyuldin Graham Horler Greg Price