Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overwrite auto_now for unittest

I've defined some timestamps for events in the database as auto_now_add, as the information should be stored with it's timestamp the same time the event is stored.

The description of the events is something like

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

To test the module, I'm generating some information in the database in the test.py file, this way:

    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()

I must generate events with its timestamp of yesterday (the module will then summarize them). The problem is that you can't overwrite the timestamp. The timestamp it's the one when the event it's produced, the documentation states that very clearly.

So, how to generate data with appropiate timestamps for the testing? I've had several ideas:

  • Maybe generate the database data in a different way, outside the Model classes. Where and how?
  • Somehow define a different class or change the class to behave differently during test, something like

_

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

Or maybe there's an even easier way to do this... Any ideas?

like image 813
Khelben Avatar asked Feb 16 '10 14:02

Khelben


1 Answers

Another way of handling this is to use a QuerySet update after the instance is created which may be more useful depending upon your use case.

As an update call is performed at the SQL level it will skip validation, signals and and custom save functionality. It will require a secondary database call which can impact performance so it should be used with consideration.

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)
like image 92
Stuart Dines Avatar answered Oct 23 '22 08:10

Stuart Dines