diff --git a/changelog/5390.bugfix.rst b/changelog/5390.bugfix.rst new file mode 100644 index 00000000000..3f57c3043d5 --- /dev/null +++ b/changelog/5390.bugfix.rst @@ -0,0 +1 @@ +Fix regression where the ``obj`` attribute of ``TestCase`` items was no longer bound to methods. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index e2e7efdc539..3ff6f45d8db 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -114,6 +114,7 @@ class TestCaseFunction(Function): def setup(self): self._testcase = self.parent.obj(self.name) self._fix_unittest_skip_decorator() + self._obj = getattr(self._testcase, self.name) if hasattr(self, "_request"): self._request._fillfixtures() @@ -132,6 +133,7 @@ def _fix_unittest_skip_decorator(self): def teardown(self): self._testcase = None + self._obj = None def startTest(self, testcase): pass diff --git a/testing/test_unittest.py b/testing/test_unittest.py index bb41952abbe..e9982b3d5b9 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -144,6 +144,29 @@ def test_func2(self): reprec.assertoutcome(passed=2) +def test_function_item_obj_is_instance(testdir): + """item.obj should be a bound method on unittest.TestCase function items (#5390).""" + testdir.makeconftest( + """ + def pytest_runtest_makereport(item, call): + if call.when == 'call': + class_ = item.parent.obj + assert isinstance(item.obj.__self__, class_) + """ + ) + testdir.makepyfile( + """ + import unittest + + class Test(unittest.TestCase): + def test_foo(self): + pass + """ + ) + result = testdir.runpytest_inprocess() + result.stdout.fnmatch_lines(["* 1 passed in*"]) + + def test_teardown(testdir): testpath = testdir.makepyfile( """