From 92403a9da399e8d66ac95c3470f961fc3d22812b Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 17 Jun 2018 20:59:17 +0100 Subject: [PATCH 1/2] Fix classmethod check for mixin case I have a case of using a mixin on my test classes that started failing with 3.3.0 in upgrade PR adamchainz/django-mysql#484. It was caused by #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. --- pytest_django/plugin.py | 3 ++- tests/test_unittest.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 4c403da9e..0a1cd0cc2 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -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:]: 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) diff --git a/tests/test_unittest.py b/tests/test_unittest.py index d4ecbc381..98699ab80 100644 --- a/tests/test_unittest.py +++ b/tests/test_unittest.py @@ -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 From 07a03fa3b5c67c15ddeb71a083c3459984d7a42e Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 18 Jun 2018 19:12:19 +0200 Subject: [PATCH 2/2] fixup! Fix classmethod check for mixin case --- pytest_django/plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 0a1cd0cc2..3f499715b 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -263,7 +263,7 @@ def pytest_configure(): def _classmethod_is_defined_at_leaf(cls, method_name): super_method = None - for base_cls in cls.__mro__[1:]: + for base_cls in cls.__mro__[1:]: # pragma: no branch if hasattr(base_cls, method_name): super_method = getattr(base_cls, method_name) break