diff --git a/CHANGELOG b/CHANGELOG index d34af05b0..367e3cefb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ Changes between 2.0.0 and 2.0.1.devX ---------------------------------------------- + - fix issue12 - show plugin versions with "--version" and "--traceconfig" and also document how to add extra information to reporting test header @@ -34,6 +35,12 @@ Changes between 2.0.0 and 2.0.1.devX - introduce a mechanism to prevent/unregister plugins from the command line, see http://pytest.org/plugins.html#cmdunregister - activate resultlog plugin by default +- fix regression wrt yielded tests which due to the + collection-before-running semantics were not + setup as with pytest 1.3.4. Note, however, that + the recommended and much cleaner way to do test + parametraization remains the "pytest_generate_tests" + mechanism, see the docs. Changes between 1.3.4 and 2.0.0 ---------------------------------------------- diff --git a/_pytest/python.py b/_pytest/python.py index 64e48b763..f46258522 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -304,7 +304,9 @@ class FunctionMixin(PyobjMixin): name = 'setup_method' else: name = 'setup_function' - if isinstance(self.parent, Instance): + if hasattr(self, '_preservedparent'): + obj = self._preservedparent + elif isinstance(self.parent, Instance): obj = self.parent.newinstance() self.obj = self._getobj() else: @@ -377,7 +379,8 @@ class Generator(FunctionMixin, PyCollectorMixin, pytest.Collector): # invoke setup/teardown on popular request # (induced by the common "test_*" naming shared with normal tests) self.config._setupstate.prepare(self) - + # see FunctionMixin.setup and test_setupstate_is_preserved_134 + self._preservedparent = self.parent.obj l = [] seen = {} for i, x in enumerate(self.obj()): diff --git a/testing/test_python.py b/testing/test_python.py index a2d9e3670..3ee149357 100644 --- a/testing/test_python.py +++ b/testing/test_python.py @@ -196,6 +196,49 @@ class TestGenerator: assert passed == 4 assert not skipped and not failed + def test_setupstate_is_preserved_134(self, testdir): + # yield-based tests are messy wrt to setupstate because + # during collection they already invoke setup functions + # and then again when they are run. For now, we want to make sure + # that the old 1.3.4 behaviour is preserved such that all + # yielded functions all share the same "self" instance that + # has been used during collection. + o = testdir.makepyfile(""" + setuplist = [] + class TestClass: + def setup_method(self, func): + #print "setup_method", self, func + setuplist.append(self) + self.init = 42 + + def teardown_method(self, func): + self.init = None + + def test_func1(self): + pass + + def test_func2(self): + yield self.func2 + yield self.func2 + + def func2(self): + assert self.init + + def test_setuplist(): + # once for test_func2 during collection + # once for test_func1 during test run + # once for test_func2 during test run + #print setuplist + assert len(setuplist) == 3, len(setuplist) + assert setuplist[0] == setuplist[2], setuplist + assert setuplist[1] != setuplist[2], setuplist + """) + reprec = testdir.inline_run(o, '-v') + passed, skipped, failed = reprec.countoutcomes() + assert passed == 4 + assert not skipped and not failed + + class TestFunction: def test_getmodulecollector(self, testdir): item = testdir.getitem("def test_func(): pass")