From beaa8e55bd6453a929c458570678c4d4b0d4bed3 Mon Sep 17 00:00:00 2001 From: Galaczi Endre Date: Mon, 21 Sep 2015 14:18:29 +0100 Subject: [PATCH 01/29] Fixes #653 use deprecated_call as context_manager --- AUTHORS | 1 + CHANGELOG | 1 + _pytest/recwarn.py | 11 ++++++++++- doc/en/recwarn.rst | 6 ++++++ testing/test_recwarn.py | 11 +++++++++++ 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 0b0f1005261..49bd6ca85ec 100644 --- a/AUTHORS +++ b/AUTHORS @@ -28,6 +28,7 @@ Dave Hunt David Mohr Edison Gustavo Muenz Eduardo Schettino +Endre Galaczi Elizaveta Shashkova Eric Hunsberger Eric Siegerman diff --git a/CHANGELOG b/CHANGELOG index 9cc6d628cf1..465ca2f0eb2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,7 @@ - Fix issue #411: Add __eq__ method to assertion comparison example. Thanks Ben Webb. +- Fix issue #653: deprecated_call can be used as context manager. 2.8.0 ----------------------------- diff --git a/_pytest/recwarn.py b/_pytest/recwarn.py index abefdfac129..a4e2d763c6a 100644 --- a/_pytest/recwarn.py +++ b/_pytest/recwarn.py @@ -28,9 +28,18 @@ def pytest_namespace(): 'warns': warns} -def deprecated_call(func, *args, **kwargs): +def deprecated_call(func=None, *args, **kwargs): """Assert that ``func(*args, **kwargs)`` triggers a DeprecationWarning. + + This function can be used as a context manager:: + + >>> with deprecated_call(): + ... myobject.deprecated_method() """ + if not func: + warnings.simplefilter('always') + return WarningsChecker(expected_warning=DeprecationWarning) + wrec = WarningsRecorder() with wrec: warnings.simplefilter('always') # ensure all warnings are triggered diff --git a/doc/en/recwarn.rst b/doc/en/recwarn.rst index c2a1e65fa17..ead162f4ed8 100644 --- a/doc/en/recwarn.rst +++ b/doc/en/recwarn.rst @@ -114,3 +114,9 @@ command ``warnings.simplefilter('always')``:: warnings.warn("deprecated", DeprecationWarning) assert len(recwarn) == 1 assert recwarn.pop(DeprecationWarning) + +You can also use it as a contextmanager:: + + def test_global(): + with pytest.deprecated_call(): + myobject.deprecated_method() diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 644b09ef754..f441187a665 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -79,6 +79,7 @@ def dep_explicit(i): filename="hello", lineno=3) class TestDeprecatedCall(object): + def test_deprecated_call_raises(self): excinfo = pytest.raises(AssertionError, "pytest.deprecated_call(dep, 3)") @@ -111,6 +112,16 @@ def test_deprecated_explicit_call(self): pytest.deprecated_call(dep_explicit, 0) pytest.deprecated_call(dep_explicit, 0) + def test_deprecated_call_as_context_manager_no_warning(self): + with pytest.raises(pytest.fail.Exception) as ex: + with pytest.deprecated_call(): + dep(1) + assert str(ex.value) == "DID NOT WARN" + + def test_deprecated_call_as_context_manager(self): + with pytest.deprecated_call(): + dep(0) + class TestWarns(object): def test_strings(self): From 9f77a8507efe8e5e021c7a65342b2b01aefb6765 Mon Sep 17 00:00:00 2001 From: Galaczi Endre Date: Mon, 21 Sep 2015 15:54:50 +0100 Subject: [PATCH 02/29] removed mutation of global state, changed filter addition in WarningsRecorder --- _pytest/recwarn.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/_pytest/recwarn.py b/_pytest/recwarn.py index a4e2d763c6a..5e7cdd84b3e 100644 --- a/_pytest/recwarn.py +++ b/_pytest/recwarn.py @@ -37,7 +37,6 @@ def deprecated_call(func=None, *args, **kwargs): ... myobject.deprecated_method() """ if not func: - warnings.simplefilter('always') return WarningsChecker(expected_warning=DeprecationWarning) wrec = WarningsRecorder() @@ -158,8 +157,8 @@ def showwarning(message, category, filename, lineno, self._module.showwarning = showwarning # allow the same warning to be raised more than once - self._module.simplefilter('always', append=True) + self._module.simplefilter('always') return self def __exit__(self, *exc_info): From d8fbb0b8e3e2d21fc30a74eb9165edc2c838893d Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 22 Sep 2015 11:00:55 +0200 Subject: [PATCH 03/29] start features branch --- CHANGELOG | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d17d29defa2..ed7d70b14ed 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,16 +1,6 @@ -2.8.x ------ +2.9.0.dev +--------- -- (experimental) adapt more SEMVER style versioning and change meaning of - master branch in git repo: "master" branch now keeps the bugfixes, changes - aimed for micro releases. "features" branch will only be be released - with minor or major pytest releases. - -- Fix issue #766 by removing documentation references to distutils. - Thanks Russel Winder. - -- Fix issue #411: Add __eq__ method to assertion comparison example. - Thanks Ben Webb. 2.8.0 ----------------------------- From 97f7815febde7b5425e789fd72e9ad63e1c2f2d2 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 22 Sep 2015 11:01:33 +0200 Subject: [PATCH 04/29] also change pytest version to target 2.9.0 --- _pytest/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_pytest/__init__.py b/_pytest/__init__.py index e1978cb3516..51751401b64 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '2.8.0' +__version__ = '2.9.0.dev1' From 8a4517fd17325fa0716ddda7a2eb7a0ad7b1e7f3 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 22 Sep 2015 11:05:19 +0200 Subject: [PATCH 05/29] re-add 2.8.x changelog so that MASTER can be merged into features wrt to the changelog --- CHANGELOG | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index ed7d70b14ed..9d454770a33 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,19 @@ 2.9.0.dev --------- +2.8.x +----- + +- (experimental) adapt more SEMVER style versioning and change meaning of + master branch in git repo: "master" branch now keeps the bugfixes, changes + aimed for micro releases. "features" branch will only be be released + with minor or major pytest releases. + +- Fix issue #766 by removing documentation references to distutils. + Thanks Russel Winder. + +- Fix issue #411: Add __eq__ method to assertion comparison example. + Thanks Ben Webb. 2.8.0 ----------------------------- From 7c088d11045886874e29fb413c7840c3372b0177 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 22 Sep 2015 11:23:24 +0200 Subject: [PATCH 06/29] remove nonsense line --- CHANGELOG | 3 --- 1 file changed, 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 4478439c6ba..d74db53c120 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,5 @@ 2.9.0.dev --------- - -2.8.x ------ 2.8.1.dev --------- From b71add27daffb0bfb2719828b6a1755486092984 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Mon, 21 Sep 2015 11:32:17 +0100 Subject: [PATCH 07/29] Add MarkEvaluator for skip --- _pytest/skipping.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index 36e54d7d8ae..2ecef01dd77 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -147,10 +147,16 @@ def getexplanation(self): @pytest.hookimpl(tryfirst=True) def pytest_runtest_setup(item): - evalskip = MarkEvaluator(item, 'skipif') - if evalskip.istrue(): - item._evalskip = evalskip - pytest.skip(evalskip.getexplanation()) + eval_skipif = MarkEvaluator(item, 'skipif') + eval_skip = MarkEvaluator(item, 'skip') + + if eval_skipif.istrue(): + item._evalskip = eval_skipif + pytest.skip(eval_skipif.getexplanation()) + elif eval_skip.istrue(): + item._evalskip = eval_skip + pytest.skip(eval_skip.getexplanation()) + item._evalxfail = MarkEvaluator(item, 'xfail') check_xfail_no_run(item) From 4e94135d361c541a579180e25a55cbfa38021565 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Mon, 21 Sep 2015 12:11:20 +0100 Subject: [PATCH 08/29] Remove incorrect use of pytest.mark.skip --- testing/test_capture.py | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/test_capture.py b/testing/test_capture.py index 53933352573..b5b374a726b 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -556,7 +556,6 @@ def test_a(): import subprocess subprocess.call([sys.executable, __file__]) - @pytest.mark.skip def test_foo(): import os;os.write(1, b'\xc3') From f144666f8bcb468c89d938c919af4bc43c935704 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Mon, 21 Sep 2015 12:20:49 +0100 Subject: [PATCH 09/29] Work towards test coverage of mark.skip --- testing/test_skipping.py | 43 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 1048c9455fb..2d12af42765 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -382,7 +382,48 @@ def test_func(): ]) -class TestSkipif: +class TestSkip(object): + def test_skip_no_reason(self, testdir): + testdir.makepyfile(""" + import pytest + @pytest.mark.skip + def test_foo(): + pass + """) + rec = testdir.inline_run() + rec.assertoutcome(skipped=1) + + def test_skip_with_reason(self, testdir): + testdir.makepyfile(""" + import pytest + @pytest.mark.skip(reason="for lolz") + def test_bar(): + pass + """) + # cant use assertoutcome because we cant + # also check the reason + result = testdir.runpytest('-rs') + result.stdout.fnmatch_lines([ + "*for lolz*", + "*1 skipped*", + ]) + + def test_only_skips_marked_test(self, testdir): + testdir.makepyfile(""" + import pytest + @pytest.mark.skip + def test_foo(): + pass + @pytest.mark.skip(reason="none") + def test_bar() : + pass + def test_baz(): + assert True + """) + rec = testdir.inline_run() + rec.assertoutcome(passed=1, skipped=2) + +class TestSkipif(object): def test_skipif_conditional(self, testdir): item = testdir.getitem(""" import pytest From ad0b8e31b8c43d6ca0f2379703c1013982633ab2 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Mon, 21 Sep 2015 15:19:29 +0100 Subject: [PATCH 10/29] Fix case where skip is assigned to as an attribute directly --- _pytest/skipping.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index 2ecef01dd77..2733cac16cf 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -5,6 +5,7 @@ import py import pytest +from _pytest.mark import MarkInfo def pytest_addoption(parser): group = parser.getgroup("general") @@ -148,14 +149,15 @@ def getexplanation(self): @pytest.hookimpl(tryfirst=True) def pytest_runtest_setup(item): eval_skipif = MarkEvaluator(item, 'skipif') - eval_skip = MarkEvaluator(item, 'skip') if eval_skipif.istrue(): item._evalskip = eval_skipif pytest.skip(eval_skipif.getexplanation()) - elif eval_skip.istrue(): - item._evalskip = eval_skip - pytest.skip(eval_skip.getexplanation()) + elif isinstance(item.keywords.get('skip'), MarkInfo): + eval_skip = MarkEvaluator(item, 'skip') + if eval_skip.istrue(): + item._evalskip = eval_skip + pytest.skip(eval_skip.getexplanation()) item._evalxfail = MarkEvaluator(item, 'xfail') check_xfail_no_run(item) From 61b8443723101d5419a50c97e80fd2329b8197b5 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Mon, 21 Sep 2015 15:29:07 +0100 Subject: [PATCH 11/29] Update docs with new skip marker --- doc/en/skipping.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index fc4f66e76bb..b3eff61abb8 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -31,7 +31,15 @@ Marking a test function to be skipped .. versionadded:: 2.0, 2.4 -Here is an example of marking a test function to be skipped +The simplest way to skip a function is to mark it with the `skip` decorator, +which may be passed an optional `reason`: + + @pytest.mark.skip(reason="no way of currently testing this") + def test_the_unknown(): + ... + +If you wish to skip something conditionally then you can use `skipif` instead. +Here is an example of marking a test function to bwe skipped when run on a Python3.3 interpreter:: import sys From 5ec08d308182d2b9c15def469b0062e8c3deca30 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Mon, 21 Sep 2015 15:29:50 +0100 Subject: [PATCH 12/29] Delete trailing whitespace --- doc/en/skipping.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index b3eff61abb8..fb416d3e0a4 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -29,15 +29,15 @@ corresponding to the "short" letters shown in the test progress:: Marking a test function to be skipped ------------------------------------------- -.. versionadded:: 2.0, 2.4 - -The simplest way to skip a function is to mark it with the `skip` decorator, -which may be passed an optional `reason`: +The simplest way to skip a function is to mark it with the `skip` decorator +(added in 2.8) which may be passed an optional `reason`: @pytest.mark.skip(reason="no way of currently testing this") def test_the_unknown(): ... +.. versionadded:: 2.0, 2.4 + If you wish to skip something conditionally then you can use `skipif` instead. Here is an example of marking a test function to bwe skipped when run on a Python3.3 interpreter:: @@ -176,12 +176,12 @@ Running it with the report-on-xfail option gives this output:: platform linux -- Python 3.4.3, pytest-2.8.1, py-1.4.30, pluggy-0.3.1 rootdir: $REGENDOC_TMPDIR/example, inifile: collected 7 items - + xfail_demo.py xxxxxxx ======= short test summary info ======== XFAIL xfail_demo.py::test_hello XFAIL xfail_demo.py::test_hello2 - reason: [NOTRUN] + reason: [NOTRUN] XFAIL xfail_demo.py::test_hello3 condition: hasattr(os, 'sep') XFAIL xfail_demo.py::test_hello4 @@ -191,7 +191,7 @@ Running it with the report-on-xfail option gives this output:: XFAIL xfail_demo.py::test_hello6 reason: reason XFAIL xfail_demo.py::test_hello7 - + ======= 7 xfailed in 0.12 seconds ======== .. _`skip/xfail with parametrize`: From dc7153e33cc89895311637a2f57e878549d4d6ca Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Mon, 21 Sep 2015 15:33:48 +0100 Subject: [PATCH 13/29] Spelling and grammar fixes --- doc/en/skipping.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index fb416d3e0a4..ffb5732b740 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -29,7 +29,7 @@ corresponding to the "short" letters shown in the test progress:: Marking a test function to be skipped ------------------------------------------- -The simplest way to skip a function is to mark it with the `skip` decorator +The simplest way to skip a test function is to mark it with the `skip` decorator (added in 2.8) which may be passed an optional `reason`: @pytest.mark.skip(reason="no way of currently testing this") @@ -39,7 +39,7 @@ The simplest way to skip a function is to mark it with the `skip` decorator .. versionadded:: 2.0, 2.4 If you wish to skip something conditionally then you can use `skipif` instead. -Here is an example of marking a test function to bwe skipped +Here is an example of marking a test function to be skipped when run on a Python3.3 interpreter:: import sys From 771aef9ddbd7927e30656aedc20aee5ca9fd8b8d Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Mon, 21 Sep 2015 15:47:11 +0100 Subject: [PATCH 14/29] Add a test_skip_class test --- testing/test_skipping.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 2d12af42765..22e5d7302c3 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -383,6 +383,22 @@ def test_func(): class TestSkip(object): + def test_skip_class(self, testdir): + testdir.makepyfile(""" + import pytest + @pytest.mark.skip + class TestSomething(object): + def test_foo(self): + pass + def test_bar(self): + pass + + def test_baz(): + pass + """) + rec = testdir.inline_run() + rec.assertoutcome(skipped=2, passed=1) + def test_skip_no_reason(self, testdir): testdir.makepyfile(""" import pytest From abc27f56fcb49bd419dfd09b0492509fa0555684 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Wed, 23 Sep 2015 15:04:04 +0100 Subject: [PATCH 15/29] Update skipping.rst with correct version marker --- doc/en/skipping.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index ffb5732b740..25e3c81163c 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -29,8 +29,10 @@ corresponding to the "short" letters shown in the test progress:: Marking a test function to be skipped ------------------------------------------- +.. versionadded:: 2.9 + The simplest way to skip a test function is to mark it with the `skip` decorator -(added in 2.8) which may be passed an optional `reason`: +which may be passed an optional `reason`: @pytest.mark.skip(reason="no way of currently testing this") def test_the_unknown(): From d1628944a667c8007da1fc2ff897adaf7a80f985 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Sun, 27 Sep 2015 22:49:09 +0100 Subject: [PATCH 16/29] Update skippings tests for better coverage --- testing/test_skipping.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 22e5d7302c3..b0d3beff3d0 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -399,6 +399,16 @@ def test_baz(): rec = testdir.inline_run() rec.assertoutcome(skipped=2, passed=1) + def test_skips_on_false_string(self, testdir): + testdir.makepyfile(""" + import pytest + @pytest.mark.skip('False') + def test_foo(): + pass + """) + rec = testdir.inline_run() + rec.assertoutcome(skipped=1) + def test_skip_no_reason(self, testdir): testdir.makepyfile(""" import pytest @@ -430,14 +440,19 @@ def test_only_skips_marked_test(self, testdir): @pytest.mark.skip def test_foo(): pass - @pytest.mark.skip(reason="none") - def test_bar() : + @pytest.mark.skip(reason="no reason") + def test_bar(): pass def test_baz(): assert True """) - rec = testdir.inline_run() - rec.assertoutcome(passed=1, skipped=2) + # cant use assertoutcome because we cant + # also check the reason + result = testdir.runpytest('-rs') + result.stdout.fnmatch_lines([ + "*no reason*", + "*1 passed*2 skipped*", + ]) class TestSkipif(object): def test_skipif_conditional(self, testdir): From 04545f8a54c6a5e8e11932f4a045fb2f51a52013 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Thu, 1 Oct 2015 21:55:51 +0100 Subject: [PATCH 17/29] classes inherit from object --- _pytest/skipping.py | 2 +- testing/test_skipping.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index 2733cac16cf..93faa4c9b0c 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -51,7 +51,7 @@ def xfail(reason=""): raise XFailed(reason) xfail.Exception = XFailed -class MarkEvaluator: +class MarkEvaluator(object): def __init__(self, item, name): self.item = item self.name = name diff --git a/testing/test_skipping.py b/testing/test_skipping.py index b0d3beff3d0..d7ceb5cfc0b 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -4,7 +4,7 @@ from _pytest.skipping import MarkEvaluator, folded_skips, pytest_runtest_setup from _pytest.runner import runtestprotocol -class TestEvaluator: +class TestEvaluator(object): def test_no_marker(self, testdir): item = testdir.getitem("def test_func(): pass") evalskipif = MarkEvaluator(item, 'skipif') @@ -125,7 +125,7 @@ def test_func(self): assert expl == "condition: config._hackxyz" -class TestXFail: +class TestXFail(object): def test_xfail_simple(self, testdir): item = testdir.getitem(""" import pytest @@ -350,7 +350,7 @@ def test_raises(): ]) -class TestXFailwithSetupTeardown: +class TestXFailwithSetupTeardown(object): def test_failing_setup_issue9(self, testdir): testdir.makepyfile(""" import pytest From eee24138b037daa4dd662d1a1e2d7541cef25b92 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Thu, 1 Oct 2015 21:56:09 +0100 Subject: [PATCH 18/29] Fix failing test --- _pytest/skipping.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index 93faa4c9b0c..53c7311e3f6 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -155,9 +155,8 @@ def pytest_runtest_setup(item): pytest.skip(eval_skipif.getexplanation()) elif isinstance(item.keywords.get('skip'), MarkInfo): eval_skip = MarkEvaluator(item, 'skip') - if eval_skip.istrue(): - item._evalskip = eval_skip - pytest.skip(eval_skip.getexplanation()) + item._evalskip = eval_skip + pytest.skip(eval_skip.getexplanation()) item._evalxfail = MarkEvaluator(item, 'xfail') check_xfail_no_run(item) From 1b5aa2868de5d7ab3ec99c0c4c11836dde85f9cf Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Thu, 1 Oct 2015 21:56:15 +0100 Subject: [PATCH 19/29] Check no reason displayed if none specified --- testing/test_skipping.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index d7ceb5cfc0b..c7a0516b4e1 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -416,8 +416,11 @@ def test_skip_no_reason(self, testdir): def test_foo(): pass """) - rec = testdir.inline_run() - rec.assertoutcome(skipped=1) + result = testdir.runpytest('-rs') + result.stdout.fnmatch_lines([ + "*Skipped instance*", + "*1 skipped*", + ]) def test_skip_with_reason(self, testdir): testdir.makepyfile(""" From 9e57954b0388d2830dee1e560347af581b75534a Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Thu, 1 Oct 2015 22:35:38 +0100 Subject: [PATCH 20/29] First argument in pytest.mark.skip is a reason --- _pytest/skipping.py | 27 ++++++++++++++++++--------- testing/test_skipping.py | 13 +++++++++++++ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index 53c7311e3f6..491dd66a9e0 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -148,15 +148,24 @@ def getexplanation(self): @pytest.hookimpl(tryfirst=True) def pytest_runtest_setup(item): - eval_skipif = MarkEvaluator(item, 'skipif') - - if eval_skipif.istrue(): - item._evalskip = eval_skipif - pytest.skip(eval_skipif.getexplanation()) - elif isinstance(item.keywords.get('skip'), MarkInfo): - eval_skip = MarkEvaluator(item, 'skip') - item._evalskip = eval_skip - pytest.skip(eval_skip.getexplanation()) + # Check if skip or skipif are specified as pytest marks + + skipif_info = item.keywords.get('skipif') + if isinstance(skipif_info, MarkInfo): + eval_skipif = MarkEvaluator(item, 'skipif') + if eval_skipif.istrue(): + item._evalskip = eval_skipif + pytest.skip(eval_skipif.getexplanation()) + + skip_info = item.keywords.get('skip') + if isinstance(skip_info, MarkInfo): + item._evalskip = True + if 'reason' in skip_info.kwargs: + pytest.skip(skip_info.kwargs['reason']) + elif skip_info.args: + pytest.skip(skip_info.args[0]) + else: + pytest.skip() item._evalxfail = MarkEvaluator(item, 'xfail') check_xfail_no_run(item) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index c7a0516b4e1..05e0683c5e8 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -409,6 +409,19 @@ def test_foo(): rec = testdir.inline_run() rec.assertoutcome(skipped=1) + def test_arg_as_reason(self, testdir): + testdir.makepyfile(""" + import pytest + @pytest.mark.skip('testing stuff') + def test_bar(): + pass + """) + result = testdir.runpytest('-rs') + result.stdout.fnmatch_lines([ + "*testing stuff*", + "*1 skipped*", + ]) + def test_skip_no_reason(self, testdir): testdir.makepyfile(""" import pytest From 213dbe7a5f28da38b62e7828d3c1d866fe996b4b Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Thu, 1 Oct 2015 22:36:43 +0100 Subject: [PATCH 21/29] newlines --- _pytest/skipping.py | 6 ++++++ testing/test_skipping.py | 1 + 2 files changed, 7 insertions(+) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index 491dd66a9e0..c3b7f7b77ba 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -7,12 +7,14 @@ import pytest from _pytest.mark import MarkInfo + def pytest_addoption(parser): group = parser.getgroup("general") group.addoption('--runxfail', action="store_true", dest="runxfail", default=False, help="run tests even if they are marked xfail") + def pytest_configure(config): if config.option.runxfail: old = pytest.xfail @@ -39,18 +41,22 @@ def nop(*args, **kwargs): "See http://pytest.org/latest/skipping.html" ) + def pytest_namespace(): return dict(xfail=xfail) + class XFailed(pytest.fail.Exception): """ raised from an explicit call to pytest.xfail() """ + def xfail(reason=""): """ xfail an executing test or setup functions with the given reason.""" __tracebackhide__ = True raise XFailed(reason) xfail.Exception = XFailed + class MarkEvaluator(object): def __init__(self, item, name): self.item = item diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 05e0683c5e8..f9cf9354f10 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -4,6 +4,7 @@ from _pytest.skipping import MarkEvaluator, folded_skips, pytest_runtest_setup from _pytest.runner import runtestprotocol + class TestEvaluator(object): def test_no_marker(self, testdir): item = testdir.getitem("def test_func(): pass") From 25d74a591966a4aa3852cbffab0865224a9ae0e0 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Sat, 3 Oct 2015 16:55:04 +0100 Subject: [PATCH 22/29] Dont explicitly inherit from object --- _pytest/skipping.py | 2 +- testing/test_skipping.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index c3b7f7b77ba..5dbce75ed59 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -57,7 +57,7 @@ def xfail(reason=""): xfail.Exception = XFailed -class MarkEvaluator(object): +class MarkEvaluator: def __init__(self, item, name): self.item = item self.name = name diff --git a/testing/test_skipping.py b/testing/test_skipping.py index f9cf9354f10..c72fca3c0ce 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -5,7 +5,7 @@ from _pytest.runner import runtestprotocol -class TestEvaluator(object): +class TestEvaluator: def test_no_marker(self, testdir): item = testdir.getitem("def test_func(): pass") evalskipif = MarkEvaluator(item, 'skipif') @@ -351,7 +351,7 @@ def test_raises(): ]) -class TestXFailwithSetupTeardown(object): +class TestXFailwithSetupTeardown: def test_failing_setup_issue9(self, testdir): testdir.makepyfile(""" import pytest @@ -383,7 +383,7 @@ def test_func(): ]) -class TestSkip(object): +class TestSkip: def test_skip_class(self, testdir): testdir.makepyfile(""" import pytest @@ -471,7 +471,7 @@ def test_baz(): "*1 passed*2 skipped*", ]) -class TestSkipif(object): +class TestSkipif: def test_skipif_conditional(self, testdir): item = testdir.getitem(""" import pytest From 5ff9a0ff54d0e1a88acd01fb918dec6fc7a48426 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Sat, 3 Oct 2015 16:59:27 +0100 Subject: [PATCH 23/29] Remove redundant comments --- testing/test_skipping.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index c72fca3c0ce..edb458e9129 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -443,8 +443,6 @@ def test_skip_with_reason(self, testdir): def test_bar(): pass """) - # cant use assertoutcome because we cant - # also check the reason result = testdir.runpytest('-rs') result.stdout.fnmatch_lines([ "*for lolz*", @@ -463,8 +461,6 @@ def test_bar(): def test_baz(): assert True """) - # cant use assertoutcome because we cant - # also check the reason result = testdir.runpytest('-rs') result.stdout.fnmatch_lines([ "*no reason*", From fc0bd9412cbcece8715449916f96fc1ddc51a71f Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Sat, 3 Oct 2015 17:00:16 +0100 Subject: [PATCH 24/29] Test that "unconditional skip" is the default reason if none given --- testing/test_skipping.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index edb458e9129..4945dbc77f7 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -432,7 +432,7 @@ def test_foo(): """) result = testdir.runpytest('-rs') result.stdout.fnmatch_lines([ - "*Skipped instance*", + "*unconditional skip*", "*1 skipped*", ]) From 122980ecadf7d5b3c72b5b37f40a206681fe243a Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Sat, 3 Oct 2015 17:01:11 +0100 Subject: [PATCH 25/29] Add myself to AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 1a2d2d57219..8f348e0e28c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -52,6 +52,7 @@ Marc Schlaich Mark Abramowitz Markus Unterwaditzer Martijn Faassen +Michael Aquilina Michael Droettboom Nicolas Delaby Pieter Mulder From 00d0c74657ca912f109d851961042e9e8ada9b2c Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Sat, 3 Oct 2015 17:01:21 +0100 Subject: [PATCH 26/29] Update reason in test to prevent confusing with test_no_reason --- testing/test_skipping.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 4945dbc77f7..3a6fd5c4018 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -455,7 +455,7 @@ def test_only_skips_marked_test(self, testdir): @pytest.mark.skip def test_foo(): pass - @pytest.mark.skip(reason="no reason") + @pytest.mark.skip(reason="nothing in particular") def test_bar(): pass def test_baz(): @@ -463,7 +463,7 @@ def test_baz(): """) result = testdir.runpytest('-rs') result.stdout.fnmatch_lines([ - "*no reason*", + "*nothing in particular*", "*1 passed*2 skipped*", ]) From df874db817b50f42d6cdea088fa5f9d18c8a8e4a Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Sat, 3 Oct 2015 17:02:18 +0100 Subject: [PATCH 27/29] Update default reason to "unconditional skip" --- _pytest/skipping.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index 5dbce75ed59..47f789efbdc 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -171,7 +171,7 @@ def pytest_runtest_setup(item): elif skip_info.args: pytest.skip(skip_info.args[0]) else: - pytest.skip() + pytest.skip("unconditional skip") item._evalxfail = MarkEvaluator(item, 'xfail') check_xfail_no_run(item) From 750442909c78a837dc291fc88889a06037af9c89 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Sat, 3 Oct 2015 17:04:06 +0100 Subject: [PATCH 28/29] Add unconditional skip entry to CHANGELOG --- CHANGELOG | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 4edf322987d..a437530d09a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ -2.9.0.dev +2.9.0.dev --------- - + +* Add unconditional skip mechanism (`pytest.mark.skip`) + 2.8.1.dev 2.8.2.dev --------- @@ -29,9 +31,9 @@ "pytest-xdist" plugin, with test reports being assigned to the wrong tests. Thanks Daniel Grunwald for the report and Bruno Oliveira for the PR. -- (experimental) adapt more SEMVER style versioning and change meaning of - master branch in git repo: "master" branch now keeps the bugfixes, changes - aimed for micro releases. "features" branch will only be be released +- (experimental) adapt more SEMVER style versioning and change meaning of + master branch in git repo: "master" branch now keeps the bugfixes, changes + aimed for micro releases. "features" branch will only be be released with minor or major pytest releases. - Fix issue #766 by removing documentation references to distutils. @@ -57,7 +59,7 @@ ----------------------------- - new ``--lf`` and ``-ff`` options to run only the last failing tests or - "failing tests first" from the last run. This functionality is provided + "failing tests first" from the last run. This functionality is provided through porting the formerly external pytest-cache plugin into pytest core. BACKWARD INCOMPAT: if you used pytest-cache's functionality to persist data between test runs be aware that we don't serialize sets anymore. @@ -163,9 +165,9 @@ - fix issue735: assertion failures on debug versions of Python 3.4+ -- new option ``--import-mode`` to allow to change test module importing - behaviour to append to sys.path instead of prepending. This better allows - to run test modules against installated versions of a package even if the +- new option ``--import-mode`` to allow to change test module importing + behaviour to append to sys.path instead of prepending. This better allows + to run test modules against installated versions of a package even if the package under test has the same import root. In this example:: testing/__init__.py @@ -173,7 +175,7 @@ pkg_under_test/ the tests will run against the installed version - of pkg_under_test when ``--import-mode=append`` is used whereas + of pkg_under_test when ``--import-mode=append`` is used whereas by default they would always pick up the local version. Thanks Holger Krekel. - pytester: add method ``TmpTestdir.delete_loaded_modules()``, and call it From 8984177448a3e0b3b493dd3112bf4d6991448df1 Mon Sep 17 00:00:00 2001 From: Michael Aquilina Date: Sat, 3 Oct 2015 17:12:44 +0100 Subject: [PATCH 29/29] TestXFail also shouldnt explicitly inherit from object --- testing/test_skipping.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 3a6fd5c4018..66bfd68c20b 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -126,7 +126,7 @@ def test_func(self): assert expl == "condition: config._hackxyz" -class TestXFail(object): +class TestXFail: def test_xfail_simple(self, testdir): item = testdir.getitem(""" import pytest