python - Django unit testing with date/time-based objects -


Assume that I have the following event model:

  Django.db Import Model import datetime class event (models.Model) from: DATE_START = models.DateField () DATE_END = models.DateField () Def is_over (auto): return datetime.date.today ()> Self.date_end  

I want to test Event.is_over () by creating an event ending in the future (today + 1 or something else), and Date and time therefore the system thinks that we have reached that future date.

I want to be able to stunge all the system time objects as far as Python is concerned. It contains datetime.date.today () , datetime.datetime.now () and any other standard date / time objects.

What is the standard way to do this?

edit : Since my answer is acceptable, answer that I update it To make everyone better, this is in the meantime, asking to update the FreeJugun Library: When I want to influence time in the tests, I use it in all my projects. Have a look at this.

Basic Answer:

It is always dangerous to change the internal content because it has bad side effects. So what you really want, monkey patching as local as possible.

We use Michael Ford's excellent motive library: There is a @ patch decorator that patch up some functionality, but the monkey patch is only within the scope of the trial function. It remains the same, and after the function is out of its scope, everything is automatically restored.

There is only one problem that if the internal datetime module is implemented in C, by default you will not be able to monkey patch it. We have fixed it through our own simple implementation which can be embarrassing

The total solution is something like this (eg a validation function which is valid in the future of the Django project in a future). Please note that I took it from a project but took non-critical things, so when things can not be copied to copy-paste, but you get this idea, then I hope :)

First we define ourselves to import a very simple implementation of datetime.date.today in a file called utils / date.py (today datetime def today) : Return datetime.date.today ()

Then we unify in this code for tests.py Relationships:

@ mock.patch ('utils.date.today') def test_validate_future_date (auto, today_mock) :: import from dittest importet test import from imported datetime import datetime import from django.core.exceptions From imitation .. import authenticator class ValidationTests (testcase) ValidationError import always return the same date # so we can actually put on the unit test in future today to python today :) today_mock.return_value = datetime.date (2010, 1 , 1) # a future date validators.valid should work ate_future_date (datetime.date (2010, 1, 2)) # joke today's date self.assertRaises (ValidationError) e The form should fail with: validators.validate_future_date (datetime.date (2010, 1, 1)) self.assertEquals ([u'Date should be in the future '], e.exception.messages) # Date also in the past Should fail with .assertRaises. (ValidationError) as E: validators.validate_future_date (datetime.date (2009, 12, 31)) Self.assertEquals ([u_date should be in the future.], E.exception.messages)

The final implementation looks like this:

  import from django.utils.translation import from ugettext_lazy ValidationError import from utils import dd def validate_future_date (value) as from _django.core.exceptions: If the value is & lt; = Date.today (): Enhancement ValidationError (_ ('Date should be in the future.'))  

Hope this helps


Comments

Popular posts from this blog

c++ - Linux and clipboard -

What is expire header and how to achive them in ASP.NET and PHP? -

sql server - How can I determine which of my SQL 2005 statistics are unused? -