2010-02-16 21 views
6

Ich habe einige Zeitstempel für Ereignisse in der Datenbank als auto_now_add definiert, da die Informationen mit dem Zeitstempel der gleichen Zeit gespeichert werden sollen, zu der das Ereignis gespeichert wird.Auto_now für Unittest überschreiben

Die Beschreibung der Ereignisse ist so etwas wie

class NewEvent(models.Model): 
    ''' 
    Individual event 
    ''' 
    name = models.CharField(max_length=100) 
    quantity = models.FloatField(null=True) 
    timestamp = models.DateTimeField(auto_now_add=True) 

das Modul zu testen, ich bin in der Datenbank in der test.py Datei einige Informationen zu erzeugen, auf diese Weise:

for event in EVENT_TYPES: 
     time = datetime.datetime.now() - datetime.timedelta(days=1) 
     for i in range(48): 
      time = time.replace(hour=i/2) 
      NewEvent(name=event, 
        timestamp=time, 
        quantity=i).save() 

muss ich erzeuge Ereignisse mit ihrem Zeitstempel von gestern (das Modul wird sie dann zusammenfassen). Das Problem ist, dass Sie den Zeitstempel nicht überschreiben können. Der Zeitstempel ist der Zeitpunkt, an dem das Ereignis produziert wird, das documentation gibt dies sehr deutlich an.

Also, wie man Daten mit geeigneten Zeitstempeln für das Testen erzeugt? Ich habe mehrere Ideen gehabt:

  • Möglicherweise erzeugen Sie die Datenbankdaten auf eine andere Weise, außerhalb der Modellklassen. Wo und wie?
  • Irgendwie eine andere Klasse definieren oder die Klasse ändert unterschiedlich während des Tests, so etwas wie

_

if testing: 
    timestamp = models.DateTimeField(auto_now_add=True) 
else: 
    timestamp = models.DateTimeField(auto_now_add=False) 

Vielleicht verhält es gibt eine noch einfachere Art und Weise, dies zu tun ... Irgendwelche Ideen?

+1

Wie wäre es mit 'timestamp = models.DateTimeField (auto_now_add = testen)' als Vereinfachung? –

+0

'test' Variable wird True sein, wenn Sie testen? Das wird großartig, aber in diesem Fall sollte es so etwas wie 'auto_now_add = nicht testen' sein, denke ich ... – Khelben

+0

Es ist Ihre Frage und Ihr Beispiel, fühlen Sie sich frei, es zu reparieren. –

Antwort

2

Ich habe es geschafft, Daten zu erstellen, die die Standardwerte über ein Fixture überschreiben.

ich eine test_data.json Datei mit den Daten in folgendem Format erstellt haben:

[ 
{ 
    "model": "stats_agg.newevent", 
    "pk": 1, 
    "fields": { 
     "name": "event1", 
     "quantity":0.0, 
     "timestamp": "2010-02-15 00:27:40" 
    } 
}, 
{ 
    "model": "stats_agg.newevent", 
    "pk": 2, 
    "fields": { 
     "name": "event1", 
     "quantity":1.0, 
     "timestamp": "2010-02-15 00:27:40" 
    } 
}, 
... 

und fügen Sie dann zu der Testeinheit für mich

class SimpleTest(TestCase): 
    fixtures = ['test_data.json'] 
+1

+1: Fixtures Regel. –

+2

Leuchten regeln nicht, sie haben ernsthafte Probleme. Verwenden Sie [Fabriken] (http://factoryboy.readthedocs.org/en/latest/orms.html) – SColvin

2

Das Problem mit Vorrichtungen ist, dass ich muss getestet werden, dass bestimmte Datensätze, die älter als 30 Tage sind, nicht zurückgegeben werden, und solche, die nicht 30 Tage alt sind, zurückgegeben werden ... mit statischen Fixtures kann dies nicht (auf faule Art) getan werden. Also, was ich gewählt habe, ist die Zeitzone zu verspotten. Jetzt Funktion, die Django verwendet, um die Datetime zu verwenden.

from django.utils import timezone 

class SomeTestCase(TestCase): 
    def test_auto_add(self): 
     now = timezone.now() 
     now_31 = now - datetime.timedelta(days=31) 
     self.mock('timezone.now', returns=now_31, tracker=None) 
     SomeObject.objects.create() # has auto_now_add field ... 

für spöttische Ich benutze minimocktest

+0

Fälschen datetime ist viel bessere Option: http://tech.yunojuno.com/mocking-dates-with-django – SColvin

1

Ein anderer Weg, der Umgang mit diesem ist eine QuerySet update nach der Instanz verwendet wird erstellt, die mehr nützlich sein können Ihren Anwendungsfall abhängig von.

Wenn ein update Aufruf auf SQL-Ebene ausgeführt wird, werden Validierung, Signale und benutzerdefinierte Speicherfunktionen übersprungen. Es erfordert einen sekundären Datenbankaufruf, der sich auf die Leistung auswirken kann, so dass sie mit Überlegung verwendet werden sollte.

for event in EVENT_TYPES: 
    time = datetime.datetime.now() - datetime.timedelta(days=1) 
    for i in range(48): 
     time = time.replace(hour=i/2) 
     instance = NewEvent(name=event, quantity=i).save() 
     NewEvent.objects.filter(pk=instance.pk).update(timestamp=time)