2009-08-13 11 views
19

Próbuję uruchomić ten test: self.assertRaises(AttributeError, branch[0].childrennodes) i branch[0] nie posiada atrybut childrennodes, więc powinno być rzuca AttributeError, których assertRaises powinien złapać, ale kiedy uruchomić test, test nie powiedzie się, ponieważ jest rzucanie AttributeError.Dlaczego funkcja assertRaises nie przechwytuje mojego błędu atrybutu przy użyciu 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' 

Jakieś pomysły?

Odpowiedz

19

Myślę, że dlatego, że asert podnosi tylko akceptuje żądanie. Sprawdza, czy żądanie wywołania podnosi wyjątek, a nie samo oświadczenie.

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

powinien działać.

EDIT:

Jak THC4k poprawnie mówi, że gromadzi sprawozdania w czasie gromadzenia i błędów następnie, nie w czasie testowania.

Jest to również powód, dla którego lubię nos, ma dekorator (podwyżki), który jest przydatny i wyraźniejszy w tego rodzaju testach.

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

Ów odpowiedniego rozwiązania, ale wyjątek dzieje, gdy Python zbiera argumenty do 'self.assertRaises'. Musi ocenić 'branch [0] .childrennodes' przed wywołaniem funkcji, która podnosi wyjątek zgodnie z oczekiwaniami. –

+0

unittest ma podobne funkcje. Opisałem je w mojej własnej odpowiedzi. Uściski! –

48

Gdy test jest uruchomiony, przed wywołaniem self.assertRaises, Python musi znaleźć wartość wszystkich argumentów metody. Czyniąc to, ocenia branch[0].children_nodes, co podnosi AttributeError. Ponieważ nie wywołaliśmy jeszcze assertRaises, ten wyjątek nie zostanie przechwycony, co spowoduje niepowodzenie testu.

Roztwór do zawijania branch[0].children_nodes w funkcji lub lambda

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

assertRaises może być również stosowany jako menedżera kontekstowego (od Pythonie 2,7, lub w PyPI pakiet „unittest2”)

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

Jest to dobre rozwiązanie, ponieważ można go używać na dowolnych blokach kodu w trakcie testu, zamiast tworzyć nową funkcję tylko w celu zdefiniowania bloku kodu, do którego ma zastosowanie.

To może dać Ci dostęp do podniesionej wyjątku do dalszego przetwarzania, jeśli to konieczne:

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

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

The lambda jest super elegancki, dzięki za umieszczenie tego :) –

1

pytest ma również podobną dekorator:

from pytest import raises 

def test_raising(): 
    with raises(AttributeError): 
     branch[0].childrennodes 
Powiązane problemy