From 9275012ef789048998d1b87b9536bd7c2c063596 Mon Sep 17 00:00:00 2001 From: Daniil Galiev Date: Mon, 9 Sep 2019 00:27:55 +0500 Subject: [PATCH 1/3] fix bug with nonskipped first test in package --- AUTHORS | 1 + changelog/5830.bugfix.rst | 1 + src/_pytest/python.py | 16 ++++++++++------ testing/test_skipping.py | 23 +++++++++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 changelog/5830.bugfix.rst diff --git a/AUTHORS b/AUTHORS index e11400c1f..d0e584f63 100644 --- a/AUTHORS +++ b/AUTHORS @@ -70,6 +70,7 @@ Daniel Hahler Daniel Nuri Daniel Wandschneider Danielle Jenkins +Daniil Galiev Dave Hunt David Díaz-Barquero David Mohr diff --git a/changelog/5830.bugfix.rst b/changelog/5830.bugfix.rst new file mode 100644 index 000000000..355790fd4 --- /dev/null +++ b/changelog/5830.bugfix.rst @@ -0,0 +1 @@ +Fix fail skipping the first test in package marked as ``skip`` diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 913a93bc0..97a3ac805 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -251,18 +251,21 @@ class PyobjMixin(PyobjContext): @property def obj(self): """Underlying Python object.""" + self._mount_obj_if_needed() + return self._obj + + @obj.setter + def obj(self, value): + self._obj = value + + def _mount_obj_if_needed(self): obj = getattr(self, "_obj", None) if obj is None: self._obj = obj = self._getobj() # XXX evil hack # used to avoid Instance collector marker duplication if self._ALLOW_MARKERS: - self.own_markers.extend(get_unpacked_marks(self.obj)) - return obj - - @obj.setter - def obj(self, value): - self._obj = value + self.own_markers.extend(get_unpacked_marks(obj)) def _getobj(self): """Gets the underlying Python object. May be overwritten by subclasses.""" @@ -628,6 +631,7 @@ class Package(Module): return path in self.session._initialpaths def collect(self): + self._mount_obj_if_needed() this_path = self.fspath.dirpath() init_module = this_path.join("__init__.py") if init_module.check(file=1) and path_matches_patterns( diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 8bba479f1..371c3a4db 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -1162,3 +1162,26 @@ def test_importorskip(): match="^could not import 'doesnotexist': No module named .*", ): pytest.importorskip("doesnotexist") + + +def test_skip_package(testdir): + testdir.makepyfile( + __init__=""" + import pytest + pytestmark = pytest.mark.skip + """ + ) + + testdir.makepyfile( + """ + import pytest + def test_skip1(): + assert 0 + def test_skip2(): + assert 0 + """ + ) + + result = testdir.inline_run() + _, skipped, _ = result.listoutcomes() + assert len(skipped) == 2 From b94eb4cb7b455282144e99e9c0b21aa80596e993 Mon Sep 17 00:00:00 2001 From: Daniil Galiev Date: Thu, 12 Sep 2019 01:57:04 +0500 Subject: [PATCH 2/3] disable _ALLOW_MARKERS in module __init__.py --- src/_pytest/python.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 97a3ac805..a1f6d5067 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -548,6 +548,15 @@ class Module(nodes.File, PyCollector): return mod +class InitModule(Module): + _ALLOW_MARKERS = False + + def __repr__(self): + if type(self) == InitModule: + return "<{} {}>".format(Module.__name__, getattr(self, "name", None)) + return super().__repr__() + + class Package(Module): def __init__(self, fspath, parent=None, config=None, session=None, nodeid=None): session = parent.session @@ -637,7 +646,7 @@ class Package(Module): if init_module.check(file=1) and path_matches_patterns( init_module, self.config.getini("python_files") ): - yield Module(init_module, self) + yield InitModule(init_module, self) pkg_prefixes = set() for path in this_path.visit(rec=self._recurse, bf=True, sort=True): # We will visit our own __init__.py file, in which case we skip it. From 5cefcb20522e3d48282ba3f889162be5ef8e9040 Mon Sep 17 00:00:00 2001 From: Daniil Galiev Date: Sat, 28 Sep 2019 00:06:46 +0500 Subject: [PATCH 3/3] refactor disabling markers --- src/_pytest/python.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index a1f6d5067..45a4e66a9 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -432,6 +432,14 @@ class PyCollector(PyobjMixin, nodes.Collector): class Module(nodes.File, PyCollector): """ Collector for test classes and functions. """ + def __init__(self, fspath, parent=None, config=None, session=None, nodeid=None): + if fspath.basename == "__init__.py": + self._ALLOW_MARKERS = False + + nodes.FSCollector.__init__( + self, fspath, parent=parent, config=config, session=session, nodeid=nodeid + ) + def _getobj(self): return self._importtestmodule() @@ -548,15 +556,6 @@ class Module(nodes.File, PyCollector): return mod -class InitModule(Module): - _ALLOW_MARKERS = False - - def __repr__(self): - if type(self) == InitModule: - return "<{} {}>".format(Module.__name__, getattr(self, "name", None)) - return super().__repr__() - - class Package(Module): def __init__(self, fspath, parent=None, config=None, session=None, nodeid=None): session = parent.session @@ -646,7 +645,7 @@ class Package(Module): if init_module.check(file=1) and path_matches_patterns( init_module, self.config.getini("python_files") ): - yield InitModule(init_module, self) + yield Module(init_module, self) pkg_prefixes = set() for path in this_path.visit(rec=self._recurse, bf=True, sort=True): # We will visit our own __init__.py file, in which case we skip it.