2010-06-11 13 views
5

Ho una funzione che restituisce una tupla che, tra le altre cose, contiene un valore float. Di solito uso assertAlmostEquals per confrontarli, ma questo non funziona con le tuple. Inoltre, la tupla contiene anche altri tipi di dati. Attualmente sto affermando ogni elemento della tupla individualmente, ma questo è eccessivo per un elenco di tali tuple. C'è un buon modo per scrivere asserzioni per questi casi? Considerate questa funzione:Test asserzioni per tuple con galleggianti

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

Ora voglio scrivere un test per esso:

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

Questo fallirà perché il risultato del 1.0/2 non è esattamente 0.5. Qualcuno può raccomandare un buon modo di scrivere una tale asserzione in modo leggibile?

Modifica: In realtà 1.0/2 è esattamente 0.5, ma si ottiene il mio significato.

+0

In realtà 0,5 è esattamente rappresentabile per 'double'. – kennytm

+0

Ho appena capito anche quello - ma tu hai capito il punto generale che spero. –

risposta

7

Bene come su sfruttamento della prostituzione la vostra funzione con due cerniere:

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) 

La mia premessa è che si tratta di meglio usare più assert in un loop per ottenere i valori esatti in cui si rompe, contro l'uso di assert singolo con all().

ps. Se disponi di altri tipi numerici che desideri utilizzare assertAlmostEquals per, puoi modificare il if se sopra ad es. if type(val2) in [float, decimal.Decimal]:

2

Quello che ho fatto in passato è scrivere una funzione personalizzata che stabilisca validità per un tipo di dati complicato e quindi utilizzata assert(IsFooValid(foo)). La funzione di validità può semplicemente restituire vero/falso, ma di solito è meglio che sollevi AssertionError con un messaggio appropriato.

3

Probabilmente definirò una funzione ricorsiva.

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) 

(Si noti che sarà affermare (1, 2) e [1, 2] sono uguali.)