2010-10-06 15 views
9

Próbuję wykonać prosty test w Pythonie przy użyciu unittest, aby sprawdzić, czy klasa zgłasza wyjątek, jeśli otrzyma niewłaściwe dane wejściowe dla konstruktora. Klasa wygląda następująco:Testowanie w Pythonie - jak korzystać z assertRaises w testowaniu przy użyciu 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 

Mój test jest następujący:

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

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

Wszystko czego chcę to test się nie powiedzie, to znaczy, że wyjątek od wejścia nieodpowiednim dla konstruktora nie jest obsługiwane.

Zamiast tego pojawia się błąd: __init__() takes exactly 2 arguments (1 given).

Czego mi brakuje? Jaki jest drugi argument, który powinienem podać?

Jakiego rodzaju błędu powinienem użyć do obsługi wyjątku, że dane wejściowe, które nie mogą być dopasowane przez moje wyrażenie regularne, zostały przekazane do konstruktora?

Dziękuję, Tomas

+0

nie mogę uruchomić kod bezpośrednio tam jest błąd składni w pobliżu pętli. Czy potrafisz to skorygować? – pyfunc

+0

Pomyślałem, że wcięcie dla pętli nie było poprawne. – pyfunc

+0

@pyfunc: Przepraszam za to. Poprawiono to. –

Odpowiedz

12

To dlatego twoja klasa wymaga parametru podczas wystąpienia obiektu

podczas przechodzenia

ukol1.SummaryFormula() 

należy zostały przekazując parametr summaryFormula do niego.

ukol1.SummaryFormula(someSummaryFormula) 

Również zamieszanie dlatego, że imię i nazwisko klasa jest SummaryFormula i parametr, który można przejść do __init__ jest również SummaryFormula

czy powinno to być

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

To była oczywiście pierwsza rzecz, którą próbowałem, ale jeśli używam self.assertRaises (TypeError, ukol1.SummaryFormula ("testtest"), "testtest"), pojawia się inny błąd: SummaryFormula instance gas no __call__ method. I czy nie jest to, że podajesz argumenty przekazywane do funkcji testowanej w assertRaises jako trzeci (lub czwarty, piąty, ...) argument funkcji assertRaises()? –

+1

@ Tom Nowotny: Dodałem drugą zmianę, gdy próbowałem uruchomić twój kod. Powtarzanie tutaj: self.assertRaises (TypeError, ukol1.SummaryFormula, "testtest") – pyfunc

18

assertRaises jest trochę mylące, ponieważ musisz podać to polecenie, a nie wyrażenie, które wykonuje połączenie.

Zmień swój kod do:

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

W kodzie, jesteś wywoływania konstruktora siebie, a to podnosi wyjątek nie mając wystarczająco dużo argumentów. Zamiast tego musisz podać assertRaises do wywołania (ukol1.SummaryFormula) i argumenty do wywołania go ("testtest"). Potem może to nazwać, łapać i sprawdzać wyjątki.

2

Bardziej-generic Format alternatywny jest

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

Jest to przydatne, jeśli konstruktor jest polimorficzny i chcesz pętli nad listą różnych sposobów miswriting argumenty, np:

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

Ponieważ żaden z pozostałych odpowiedzi wskazują, w jaki sposób można korzystać z kontekstu, która zamyka kod, który wywołuje wyjątek, oto jak można to zrobić.

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

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

Atrybuty zainteresowanie tym unittest.case._AssertRaisesContext, to:

  • wyjątek
  • spodziewać
  • expected_regexp
  • failureException
Powiązane problemy