Skip to content

Commit 8a52643

Browse files
adamchainzblueyed
authored andcommitted
Fix classmethod check for mixin case
Fixes regression in #598. It looks like this was actually a latent failure in the way `_classmethod_is_defined_at_leaf` was picking the 'super method' - it would iterate further up the tree despite coming across the next method in the resolution chain. Also by not using `__mro__` the order of the base classes wasn't strictly being observed, although I don't think that affects my mixin case. Added a test that fails before and passes after. Closes #618.
1 parent 1a51148 commit 8a52643

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

docs/changelog.rst

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ Changelog
44
unreleased
55
------------------
66

7+
Bug fixes
8+
^^^^^^^^^
9+
10+
* Fixed test for classmethod with Django TestCases again (#618,
11+
introduced in #598 (3.3.0)).
12+
713
Compatibility
814
^^^^^^^^^^^^^
915

pytest_django/plugin.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,10 @@ def pytest_configure():
263263
def _classmethod_is_defined_at_leaf(cls, method_name):
264264
super_method = None
265265

266-
for base_cls in cls.__bases__:
266+
for base_cls in cls.__mro__[1:]: # pragma: no branch
267267
if hasattr(base_cls, method_name):
268268
super_method = getattr(base_cls, method_name)
269+
break
269270

270271
assert super_method is not None, (
271272
'%s could not be found in base class' % method_name)

tests/test_unittest.py

+28
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,34 @@ def test_bar21(self):
176176
])
177177
assert result.ret == 0
178178

179+
def test_setUpClass_mixin(self, django_testdir):
180+
django_testdir.create_test_module('''
181+
from django.test import TestCase
182+
183+
class TheMixin(object):
184+
@classmethod
185+
def setUpClass(cls):
186+
super(TheMixin, cls).setUpClass()
187+
188+
189+
class TestFoo(TheMixin, TestCase):
190+
def test_foo(self):
191+
pass
192+
193+
194+
class TestBar(TheMixin, TestCase):
195+
def test_bar(self):
196+
pass
197+
''')
198+
199+
result = django_testdir.runpytest_subprocess('-v', '-s', '--pdb')
200+
result.stdout.fnmatch_lines([
201+
"*TestFoo::test_foo Creating test database for*",
202+
"PASSED",
203+
"*TestBar::test_bar PASSED*",
204+
])
205+
assert result.ret == 0
206+
179207
def test_setUpClass_skip(self, django_testdir):
180208
django_testdir.create_test_module('''
181209
from django.test import TestCase

0 commit comments

Comments
 (0)