2015-04-15 2 views
36

Ho aggiornato un progetto Django 1.7 su Django 1.8 e ora ho degli errori quando eseguo i test (che sono sottoclassi di django.test.TestCase).Aggiornamento a Django 1.8 - AttributeError: django.test.TestCase non ha attributo 'cls_atomics'

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' 

Se il debug attraverso la prova che posso passare da tutte le linee senza problemi, ma dopo l'ultima riga viene lanciata l'eccezione.

Si tratta di un test di esempio:

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) 

Il mio ambiente:

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 

Come posso risolvere questo problema?

+0

Si può incollare qui un congelatore? – lapinkoira

+0

@lapinkoira fatto quello – habakuk

+1

mmm posso vedere l'implementazione del test che si esegue? – lapinkoira

risposta

60

Credo che il tuo metodo di classe setUpClass(cls) non stia chiamando super. A causa di ciò, non si chiama django.tests.TestCase.setUpClass e

cls.cls_atomics = cls._enter_atomics() 

non è chiamato, causando naturalmente cls_atomics essere indefinito.

È necessario aggiungere super(ATestTests, cls).setUpClass() al numero setUpClass.

+0

Questo è tutto. Se aggiungo la chiamata alla classe base, funziona di nuovo (ho detto che ha funzionato con django 1.7 ...). Inoltre, non ho più bisogno di chiamare 'django.setup()'. – habakuk

+0

Ho pensato di non aver bisogno di 'django.setup()' ma ho ancora bisogno in alcuni casi, altrimenti ottengo un'eccezione sul fatto che il modello non viene istanziato. – habakuk

-1

Ecco il codice completo con la chiamata alla classe di base (come suggerito da @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) 
3

Ho avuto un problema simile in cui un TestCase utilizzato setUpClass ma non ha avuto un metodo tearDownClass. I miei test passano quando aggiungo un vuoto uno:

@classmethod 
def tearDownClass(cls): 
    pass 

anche io non chiamo django.setup.

+0

Seguendo questa risposta si potrebbero avere problemi con il tuo smontaggio, in cui sono presenti oggetti e dati che non sono stati ripuliti. Ciò può causare incongruenze nella tua suite di test, in particolare se esegui operazioni in parallelo. – Jordan

+0

@Jordan - Sì, se si stanno creando oggetti persistenti, è necessario aggiungere un codice di "pulizia" effettivo al teardown, sono d'accordo. – Matt

13

Per Django 1.8+, è necessario utilizzare TestCase.setUpTestData anziché 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') 

La documentazione è here.

+0

Questo ha risolto il mio problema. Grazie! –