2010-06-11 12 views
5

Mam funkcję, która zwraca krotkę zawierającą między innymi wartość zmiennoprzecinkową. Zwykle używam assertAlmostEquals do porównywania, ale to nie działa z krotkami. Ponadto, krotka zawiera również inne typy danych. Obecnie zapewniam każdy element krotki z osobna, ale to za dużo dla listy takich krotek. Czy jest jakiś dobry sposób na napisanie twierdzeń dla takich przypadków? Rozważmy tę funkcję:Asercje testowe dla krotek z pływami

def f(a): 
    return [(1.0/x, x * 2) for x in a] 

Teraz chcę napisać test dla niego:

def testF(self): 
    self.assertEqual(f(range(1,3)), [(1.0, 2), (0.5, 4)]) 

to zawiedzie, ponieważ wynikiem 1.0/2 nie jest dokładnie 0.5. Czy ktoś może polecić dobry sposób napisania takiego stwierdzenia w czytelny sposób?

Edytuj: Rzeczywiście 1.0/2 to dokładnie 0.5, ale masz moje znaczenie.

+0

Rzeczywiście 0,5 jest dokładnie reprezentowane dla "podwójnego". – kennytm

+0

Też to wymyśliłem - ale masz ogólny punkt, który mam nadzieję. –

Odpowiedz

7

Dobrze jak o stręczycielstwo swoje funkcje z kilkoma zamkami:

def testF(self): 
    for tuple1, tuple2 in zip(f(range(1,3)), [(1.0, 2), (0.5, 4)]): 
     for val1, val2 in zip(tuple1, tuple2): 
      if type(val2) is float: 
       self.assertAlmostEquals(val1, val2, 5) 
      else: 
       self.assertEquals(val1, val2) 

Moim założeniem jest to, że jest to lepiej używać wielu znaków w pętli, aby uzyskać dokładne wartości, w których się łamie, w porównaniu z użyciem pojedynczego assert ze wszystkimi().

ps. Jeśli masz inne typy liczbowe, do których chcesz użyć assertAlmostEquals, możesz zmienić powyższe, np. if type(val2) in [float, decimal.Decimal]:

2

To, co zrobiłem w przeszłości, to napisanie funkcji niestandardowej, która określa ważność dla skomplikowanego typu danych, a następnie użyty assert(IsFooValid(foo)). Funkcja validity może po prostu zwrócić wartość true/false, ale zazwyczaj lepiej jest wywołać AssertionError z odpowiednią wiadomością.

3

Prawdopodobnie zdefiniuję funkcję rekursywną.

from collections import Iterable; 

def recursiveAssertAlmostEqual(testCase, first, second, *args, **kwargs): 
    if isinstance(first, Iterable) and isinstance(second, Iterable): 
     for a, b in zip(first, second): 
     recursiveAssertAlmostEqual(testCase, a, b, *args, **kwargs) 
    else: 
     testCase.assertAlmostEqual(first, second, *args, **kwargs) 

(Zauważ, że będzie dochodzić (1, 2) i [1, 2] są równe.)