2012-09-20 9 views
10

Ho il seguente test-codice verifica un innalzamento eccezione in una funzione. Mi aspetto che il test passi, ma viene invece indicato un errore. Ecco il codice di prova:assertRaises fallisce, anche la richiamabile solleva l'eccezione desiderata (pitone, UNITEST)

import unittest 

# define a user-defined exception 
class MyException(Exception): 
    def __str__(self): 
     return repr("ERROR: Just raised my exception!") 

# this is my main class with a method raising this exception 
class MyMainObject(object): 

    def func(self): 
     raise MyException() 

# the test class 
class TestConfig(unittest.TestCase): 

    def test_1(self): 

     other = MyMainObject() 
     self.assertRaises(MyException, other.func()) 

# calling the test 
if __name__ == '__main__':  
    unittest.main() 

Quando other.func() viene chiamato nella dichiarazione assert, MyException è sollevato (può essere controllato facilmente). Così, il test assertRaises deve superare la prova, come other.func() failes con MyException, MA:

.... 
MyException: 'ERROR: Just raised my exception!' 

---------------------------------------------------------------------- 
Ran 1 test in 0.001s 

FAILED (errors=1) 

Non vedo qualcosa di sbagliato, quindi vorrei apprezzare alcuni input su questo problema.

+1

si dovrebbe notare che è un errore, non un fallimento! la tua eccezione non è stata nemmeno catturata. –

risposta

17

assertRaises chiama la funzione per voi. Chiamando te stesso, l'eccezione viene sollevata prima delassertRaises in grado di testarlo.

modificare il codice per:

self.assertRaises(MyException, other.func) 

e funzionerà correttamente. In alternativa, è possibile utilizzare assertRaises come manager contesto (python 2.7 in su):

with self.assertRaises(MyException): 
    other.func() 

Utilizzando assertRaises come manager contesto ha il vantaggio che è ora possibile recuperare l'istanza di eccezione ed eseguire ulteriori test su di essa:

with self.assertRaises(MyException) as raises_cm: 
    other.func() 

exception = raises_cm.exception 
self.assertEqual(exception.args, ('foo', 'bar')) 
+0

Sapevo che era qualcosa di piuttosto semplice. Forse avrei dovuto guardarlo un altro giorno ... (2 minuti di attesa fino a quando non posso fare clic sul gancio) – Alex

+0

@Alex Non mi sento troppo male - Penso che questa sia più una questione di unittest che non è intuitivo - altri framework di test lavoro come ti aspettavi. – mikemaccana

+0

Sto usando l'interprete python 3.3 in IDP pycharm.Cosa succede se voglio passare argomenti alla funzione sotto test e includere anche un messaggio nel caso in cui l'errore desiderato non venga generato? Esempio - 'self.assertRaises (ValueError, person.set_age_method, -10," Errore: L'età della persona non può essere negativa. ")' Con questo, ottengo un'eccezione: 'set_age_method prende 2 argomenti posizionali ma 3 sono stati dati'. Come posso risolvere questo? A proposito, i documenti per questa asserzione non ti dicono chiaramente come farlo. https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises. Cosa è ** kwds? – testerjoe2

7

A causa delle regole dei linguaggi, gli argomenti vengono valutate prima viene immesso il codice della funzione chiamata (e che è generalmente una buona cosa). Pertanto, assertRaises non può rilevare le eccezioni che si verificano durante la valutazione degli argomenti. La soluzione (in più di un'API) è che si passa un callable a metodi come assertRaises, in modo da poter valutare in un luogo possono controllare e dove possono intercettare le eccezioni. Se l'intero argomento è una chiamata di metodo, la magia di metodi bound consente di indicarlo abbastanza elegante, senza lambda o tali sciocchezze:

self.assertRaises(MyException, other.func) # <- note, no parentheses after func 
+0

Sto usando l'interprete python 3.3 in IDP pycharm. Cosa succede se voglio passare argomenti alla funzione sotto test e includere anche un messaggio nel caso in cui l'errore desiderato non venga generato? Esempio - 'self.assertRaises (ValueError, person.set_age_method, -10," Errore: L'età della persona non può essere negativa. ")' Con questo, ottengo un'eccezione: 'set_age_method prende 2 argomenti posizionali ma 3 sono stati dati'. Come posso risolvere questo? A proposito, i documenti per questa asserzione non ti dicono chiaramente come farlo. https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises. Cosa è ** kwds? – testerjoe2

+1

@ testerjoe2 Tutto ciò che segue la funzione, inclusi argomenti di parole chiave come 'age = -10' (questo è ciò che il' ** kwds' sta per), è passato al callable. Dovresti creare direttamente l'oggetto 'ValueError', poiché la sua costruzione non ha bisogno di essere ritardata come la chiamata alla funzione (gli oggetti eccezione sono innocui se non li si" alza "), quindi si desidera:' self.assertRaises (ValueError ("Errore: l'età della persona non può essere negativa."), Person.set_age_ethod, -10) '. – delnan

Problemi correlati