mbrochh
mbrochh

Reputation: 1011

Django test fixtures: How to cope with test data involving time?

Currently I am doing TDD on a reusable Django app. One test should make sure that my view only returns articles that have a publish-date that is in the past. I am quite new to testing in Django. So far I have learned how to use .json files as fixtures for my test classes.

However for this test I do not want to insert publish dates that are 1000 years in the future. After all another species might discover our ancient internet, check out my source and wonder why my test fails :) What other approaches are there to solve this problem? Static .json files seem to be a bit hard to maintain as well as the application grows... mocking the datetime.datetime.now() method in my tests feels tedious as well.

There must be an easy way to produce the .json fixture on the fly before the test runs and always have 2 days from now as the publish-date for some of my entries...

Upvotes: 2

Views: 1565

Answers (4)

Lutz Prechelt
Lutz Prechelt

Reputation: 39446

Creating test data

Indeed it is far more flexible to create your test data with Python. There are several packages that support such things, for instance

These two use fairly different approaches. Have a look and pick the one you like more. You can also write data generation functions from scratch. If you partition your logic carefully, this is not overly cumbersome.

Handling time

For tests involving time, the right approach is indeed mocking -- but don't do it yourself, use a nice library. See for instance

There is even a pytest plugin for it.

Upvotes: 0

Paulo Cheque
Paulo Cheque

Reputation: 2836

You can try using django dynamic fixture, it will fill date/time properties automatically for you.

Upvotes: 0

mbrochh
mbrochh

Reputation: 1011

Mocking datetime was my first thought as well but as LaundroMat pointet out in his blog post himself, this is rather hacky and bad.

I came up with another solution:

I just gave up on .json fixtures. I don't even know why Django encourages to use them. They look ugly and they are impossible to maintain.

Instead I added a module test_data.py to my fixtures folder. That module imports my models and defines some nice methods that create test-data for me. In my tests.py I dropped the fixtures = ['some_json_file'] line and added a setUp() method instead. This method executes my 'dynamic fixtures' from my test_data.py module.

This is so simple and obvious that I wonder if there is anything wrong with this approach. If no one comments on this solution, I will mark is as accepted in a couple of weeks or so...

Upvotes: 1

Mathieu Dhondt
Mathieu Dhondt

Reputation: 8934

You could try subclassing the datetime functions (see "Using Mock objects in Django for testing the current date").

Upvotes: 1

Related Questions