Update to Django 1.8 - AttributeError: django.test.TestCase has no attribute 'cls_atomics'

DjangoPython 3.xDjango 1.8

Django Problem Overview


I updated a Django 1.7 project to Django 1.8 and now get errors when I run the tests (that are subclasses of django.test.TestCase).

Traceback (most recent call last):
  File "env\lib\site-packages\django\test\testcases.py", line 962, in tearDownClass
cls._rollback_atomics(cls.cls_atomics)
  AttributeError: type object 'SomeTests' has no attribute 'cls_atomics'

If I debug through the test I can step through all lines without problems, but after the last line the exception is thrown.

This is an example test:

import django
import unittest
from django.test import TestCase
import logging
import sys
from builtins import classmethod, isinstance

class ATestTests(TestCase):

	@classmethod
	def setUpClass(cls):
		django.setup()
		logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)


	def setUp(self):
		self._app = Application(name="a")


	def testtest(self):

		self.assertIsNotNone(self._app)

My environment:

astroid==1.3.4
colorama==0.3.3
defusedxml==0.4.1
Django==1.8
django-extensions==1.5.2
django-filter==0.9.2
djangorestframework==3.0.5
djangorestframework-xml==1.0.1
eight==0.3.0
future==0.11.4
logilab-common==0.63.2
Markdown==2.5.2
pylint==1.4.1
python-dateutil==2.4.1
python-mimeparse==0.1.4
six==1.9.0
xmltodict==0.9.2

How can I fix this?

Django Solutions


Solution 1 - Django

I believe the reason is that your setUpClass(cls) class method is not calling super. Because of that, django.tests.TestCase.setUpClass is not called and

cls.cls_atomics = cls._enter_atomics()

is not called, naturally causing cls_atomics to be undefined.

You should add super(ATestTests, cls).setUpClass() to your setUpClass.

Solution 2 - Django

For Django 1.8+, you should use TestCase.setUpTestData instead of TestCase.setUpClass.

class MyTests(TestCase):

    @classmethod
    def setUpTestData(cls):
        # Set up data for the whole TestCase
        cls.foo = Foo.objects.create(bar="Test")

    def test1(self):
        self.assertEqual(self.foo.bar, 'Test') 

The documentation is here.

Solution 3 - Django

I had a similar problem where a TestCase used setUpClass but did not have a tearDownClass method. My tests pass when I add an empty one:

@classmethod
def tearDownClass(cls):
    pass

I also do not call django.setup.

Solution 4 - Django

Here is the complete code with the call to the base class (as suggested by @J. C. Leitão):

import django
import unittest
from django.test import TestCase
import logging
import sys
from builtins import classmethod

class ATestTests(TestCase):

	@classmethod
	def setUpClass(cls):
		super(ATestTests, cls).setUpClass()
        django.setup()
		logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)

	def setUp(self):
		self._app = Application(name="a")

	def testtest(self):

		self.assertIsNotNone(self._app)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhabakukView Question on Stackoverflow
Solution 1 - DjangoJorge LeitaoView Answer on Stackoverflow
Solution 2 - DjangoseddonymView Answer on Stackoverflow
Solution 3 - DjangoMattView Answer on Stackoverflow
Solution 4 - DjangohabakukView Answer on Stackoverflow