2009-08-13 10 views
19

Sto provando a eseguire questo test: self.assertRaises(AttributeError, branch[0].childrennodes) e branch[0] non ha un attributo childrennodes, quindi è necessario lanciare un AttributeError, che deve essere rilevato da assertRaises, ma quando eseguo il test, il test fallisce perché è lancio di un AttributeError.Perché non è assertRaises che cattura il mio errore di attributo usando python unittest?

Traceback (most recent call last): 
    File "/home/tttt/../tttt/tests.py", line 504, in test_get_categories_branch 
    self.assertRaises(AttributeError, branch[0].children_nodes) 
AttributeError: 'Category' object has no attribute 'children_nodes' 

Qualche idea?

risposta

19

Penso che sia perché asserisce solleva accetta solo un callable. Resta da vedere se il callable solleva un'eccezione, non se l'affermazione stessa lo fa.

self.assertRaises(AttributeError, getattr, branch[0], "childrennodes") 

dovrebbe funzionare.

EDIT:

Come THC4k dice correttamente raccoglie le dichiarazioni in fase di raccolta e sarà errore poi, non in fase di test.

Anche questo è un motivo per cui mi piace il naso, ha un decoratore (alza) che è utile e più chiaro per questo tipo di test.

@raises(AttributeError) 
def test_1(self) 
    branch[0].childrennodes 
+2

Quella è la soluzione giusta, ma l'eccezione accade quando Python raccoglie gli argomenti su 'self.assertRaises'. Deve valutare 'branch [0] .childrennodes' prima di chiamare la funzione, il che solleva un'eccezione proprio come previsto. –

+0

unittest ha anche caratteristiche simili. Li ho descritti nella mia risposta. Abbracci! –

48

Quando il test è in esecuzione, prima di chiamare self.assertRaises, Python deve trovare il valore di tutti gli argomenti del metodo. In tal modo, valuta branch[0].children_nodes, che genera un errore AttributeError. Poiché non abbiamo ancora richiamato assertRaises, questa eccezione non viene rilevata, causando il fallimento del test.

La soluzione è avvolgere branch[0].children_nodes in una funzione o una lambda:

self.assertRaises(AttributeError, lambda: branch[0].children_nodes) 

assertRaises possono essere utilizzati anche come manager contesto (Da Python 2.7, o in PyPI pacchetto 'unittest2'):

with self.assertRaises(AttributeError): 
    branch[0].children_nodes 
    # etc 

Questo è bello perché può essere utilizzato su blocchi arbitrari di codice nel mezzo di un test, piuttosto che dover creare una nuova funzione solo per definire il blocco di codice a cui si applica.

Si può dare accesso al eccezione sollevata per l'ulteriore elaborazione, se necessario:

with self.assertRaises(AttributeError) as cm: 
    branch[0].children_nodes 

self.assertEquals(cm.exception.special_attribute, 123) 
+3

Il lambda è super elegante, grazie per aver postato questo :) –

1

pytest ha anche un decoratore simile:

from pytest import raises 

def test_raising(): 
    with raises(AttributeError): 
     branch[0].childrennodes 
Problemi correlati