Overwrite auto_now for unittest

I defined some timestamps for events in the database as auto_now_add , since the information should be stored along with it timestamp simultaneously with saving the event.

Description of 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 generate some information in the database in the test.py file, as follows:

  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 have to generate events with my label yesterday (the module then summarizes them). The problem is that you cannot overwrite the timestamp. This timestamp, when she created the event, the documentation , speaks very clearly about this.

So how to generate data with suitable timestamps for testing? I had a few ideas:

  • It is possible to generate 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 the test, something like

_

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

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

+6
python django unit-testing
source share
3 answers

I was able to create data overriding the default values ​​with the instrument.

I created a test_data.json file with data in the following format:

 [ { "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" } }, ... 

and then add to the test block

 class SimpleTest(TestCase): fixtures = ['test_data.json'] 
+2
source share

The problem with the tools for me is that I need to check that some records that are older than 30 days are not returned, and those that are not 30 days old are returned ... using static devices, this cannot be done (in a lazy way ) So what I decided to do was mock the timezone.now function that django uses to get datetime usage time.

 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 ... 

for ridicule I use minimocktest

+2
source share

Another way to handle this is to use a QuerySet update after creating the instance, which may be more useful depending on your use case.

As the update call is executed at the SQL level, it skips checks, signals, and custom save functions. This will require a secondary database call, which may affect 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) 
+1
source share

All Articles