2009-06-26 2 views
2

Ich muss einen Komponententest für eine Funktion schreiben, die ein Wörterbuch zurückgibt. Einer der Werte in diesem Wörterbuch ist datetime.datetime.now(), der sich natürlich bei jedem Testlauf ändert.Wörterbücher mit flüchtigen Werten in Python-Unit-Tests?

Ich möchte diesen Schlüssel vollständig in meiner Behauptung ignorieren. Im Moment habe ich ein Wörterbuch Vergleichsfunktion, aber ich möchte wirklich verwenden assertEqual wie folgt aus:

def my_func(self): 
    return {'monkey_head_count': 3, 'monkey_creation': datetime.datetime.now()} 

... unit tests 

class MonkeyTester(unittest.TestCase): 
    def test_myfunc(self): 
     self.assertEqual(my_func(), {'monkey_head_count': 3}) # I want to ignore the timestamp! 

Gibt es eine Best Practices oder elegante Lösungen für dies zu tun? Ich bin mir bewusst, assertAlmostEqual(), aber das ist nur nützlich für Floats Iirc.

Antwort

9

Löschen Sie einfach den Zeitstempel aus dem dict, bevor der Vergleich tun:

class MonkeyTester(unittest.TestCase): 
    def test_myfunc(self): 
     without_timestamp = my_func() 
     del without_timestamp["monkey_creation"] 
     self.assertEqual(without_timestamp, {'monkey_head_count': 3}) 

Wenn Sie sich finden eine Menge zeitbezogenen Tests zu tun, die beinhalten datetime.now() dann können Sie die Datetime-Klasse für die Komponententests monkeypatch. Betrachten Sie diese

import datetime 
constant_now = datetime.datetime(2009,8,7,6,5,4) 
old_datetime_class = datetime.datetime 
class new_datetime(datetime.datetime): 
    @staticmethod 
    def now(): 
     return constant_now 

datetime.datetime = new_datetime 

Nun, wenn Sie datetime.datetime.now() in Ihrer Unit-Tests aufrufen, wird es immer geben die constant_now Zeitstempel. Und wenn Sie wollen/müssen auf die ursprüngliche datetime.datetime.now() wechseln, dann können Sie einfach sagen

datetime.datetime = old_datetime_class 

und die Dinge werden wieder normal sein. So etwas kann nützlich sein, aber in dem einfachen Beispiel, das Sie angegeben haben, würde ich empfehlen, den Zeitstempel vor dem Vergleich einfach aus dem Diktat zu löschen.

+1

Warum habe ich nicht an diese einfache Lösung gedacht? Obwohl ich viele mögliche Rückgabewerte von my_func testen werde, denke ich, dass ich monateypatch datetime wie Sie vorgeschlagen haben. Viel geschätzt, wirklich schlau! – pojo

+2

Sie sollten Code setzen, um die Datetime in einer Teardown-Methode zurückzusetzen - so hat dieser Unit Test keine Auswirkungen auf andere Testklassen –

+3

Eine andere Option ist es, datetime.datetime.now als Standard für einen benannten Parameter zu übergeben; Übergeben Sie Ihre eigene Funktion im Komponententest. Dies vermeidet Monkeypatching. –

Verwandte Themen