Skip to content

Commit

Permalink
Fix classmethod check for mixin case
Browse files Browse the repository at this point in the history
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 pytest-dev/pytest-django#618.
  • Loading branch information
beyondgeeks committed Jun 18, 2018
1 parent 6822cdd commit a131717
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
6 changes: 6 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ Changelog
unreleased
------------------

Bug fixes
^^^^^^^^^

* Fixed test for classmethod with Django TestCases again (#618,
introduced in #598 (3.3.0)).

Compatibility
^^^^^^^^^^^^^

Expand Down
3 changes: 2 additions & 1 deletion pytest_django/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,10 @@ def pytest_configure():
def _classmethod_is_defined_at_leaf(cls, method_name):
super_method = None

for base_cls in cls.__bases__:
for base_cls in cls.__mro__[1:]: # pragma: no branch
if hasattr(base_cls, method_name):
super_method = getattr(base_cls, method_name)
break

assert super_method is not None, (
'%s could not be found in base class' % method_name)
Expand Down
28 changes: 28 additions & 0 deletions tests/test_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,34 @@ def test_bar21(self):
])
assert result.ret == 0

def test_setUpClass_mixin(self, django_testdir):
django_testdir.create_test_module('''
from django.test import TestCase
class TheMixin(object):
@classmethod
def setUpClass(cls):
super(TheMixin, cls).setUpClass()
class TestFoo(TheMixin, TestCase):
def test_foo(self):
pass
class TestBar(TheMixin, TestCase):
def test_bar(self):
pass
''')

result = django_testdir.runpytest_subprocess('-v', '-s', '--pdb')
result.stdout.fnmatch_lines([
"*TestFoo::test_foo Creating test database for*",
"PASSED",
"*TestBar::test_bar PASSED*",
])
assert result.ret == 0

def test_setUpClass_skip(self, django_testdir):
django_testdir.create_test_module('''
from django.test import TestCase
Expand Down

0 comments on commit a131717

Please sign in to comment.