2010-10-06 20 views
9

Sto provando a fare un semplice test in Python usando unittest, per vedere se una classe genera un'eccezione se ottiene un input non adatto per il costruttore. La classe si presenta così:Test in Python - come usare assertRaises in testing usando unittest?

class SummaryFormula: 
    def __init__(self, summaryFormula): 
     self.atoms = {} 
     for atom in re.finditer("([A-Z][a-z]{0,2})(\d*)", summaryFormula): 
      symbol = atom.group(1) 
      count = atom.group(2) 

      if pocet != "": 
       self.atoms[ symbol] = int(count) 
      else: 
       self.atoms[ symbol] = 1 

La mia prova è la seguente:

class ConstructorTestCase(unittest.TestCase): 
     def testEmptyString(self): 
     self.assertRaises(TypeError, ukol1.SummaryFormula(), "testtest") 

    if __name__ == '__main__': 
     unittest.main() 

Tutto quello che voglio è il test di fallire, il che significa che l'eccezione dell'ingresso inadatto per il costruttore non è gestita.

Invece, si verifica un errore: __init__() takes exactly 2 arguments (1 given).

Cosa mi manca? Qual è il secondo argomento che dovrei specificare?

Inoltre, quale tipo di errore dovrei usare per gestire l'eccezione che un input non accessibile dalla mia regexp è stato passato al costruttore?

Grazie, Tomas

+0

non posso eseguire il codice direttamente in quanto non vi l'errore di sintassi è vicino al ciclo. Puoi correggerlo. – pyfunc

+0

Ho pensato che la rientranza attorno al ciclo non fosse corretta – pyfunc

+0

@pyfunc: mi dispiace. Corretto –

risposta

12

Questo perché la classe richiede un parametro, mentre un'istanza dell'oggetto

mentre si sta passando

ukol1.SummaryFormula() 

si dovrebbe essere stato superato il parametro summaryFormula ad esso.

ukol1.SummaryFormula(someSummaryFormula) 

anche la confusione è perché il vostro nome della classe è SummaryFormula e il parametro che si passa a __init__ è anche SummaryFormula

o dovrebbe essere questo

self.assertRaises(TypeError, ukol1.SummaryFormula, "testtest") 
+0

Questa è stata ovviamente la prima cosa che ho provato, ma se uso self.assertRaises (TypeError, ukol1.SummaryFormula ("testtest"), "testtest"), ottengo altri errori: SummaryFormula instance gas no __call__ method. E non è che si specificano gli argomenti passati alla funzione testata in assertRaises come terzo (o quarto, quinto ...) argomento della funzione assertRaises()? –

+1

@Tomas Novotny: ho aggiunto la seconda modifica mentre cercavo di eseguire il codice. Ripetendolo qui: self.assertRaises (TypeError, ukol1.SummaryFormula, "testtest") – pyfunc

18

assertRaises è un po 'confusa, perché devi dargli il callable, non un'espressione che fa la chiamata.

modificare il codice per:

self.assertRaises(TypeError, ukol1.SummaryFormula, "testtest") 

Nel codice, si invoca il costruttore te stesso, e si solleva un'eccezione di non avere argomenti sufficienti. Invece, è necessario dare assertRaises il callable (ukol1.SummaryFormula), e gli argomenti per chiamarlo con ("testtest"). Quindi può chiamarlo, catturare e controllare le eccezioni.

2

Un formato alternativo più generico è

args=['testtest'] 
kwargs = {} 
self.assertRaises(TypeError, ukol1.SummaryFormula, *args, **kwargs) 

Questo è utile se il costruttore è polimorfa e si vuole ciclare su un elenco di modi diversi di errata trascrizione degli argomenti, ad esempio:

arg_lists = [ 
    ['testtest'], 
    ['anothertest'], 
    ['YAT'], 
] 
for args in arg_lists: 
    self.assertRaises(TypeError, ukol1.SummaryFormula, *args) 
0

Poiché nessuna delle altre risposte punto su come è possibile utilizzare il contesto che incapsula il codice che causa l'eccezione, ecco come si può fare.

with self.assertRaises(ValueError) as ctx: 
    <some code that throws an exception> 

expected_msg = 'foo_bar_baz' 
self.assertEquals(ctx.exception.message, expected_msg) 

attributi di interesse in questo unittest.case._AssertRaisesContext, sono:

  • eccezione
  • previsto
  • expected_regexp
  • failureException
Problemi correlati