Hello!

I have a code (test) that mocks datetime.datetime.now and the way queryset 
filter method works. The code is:

Mock:

@contextlib.contextmanager
def mock_now(dt_value):
    """Context manager for mocking out datetime.now() in unit tests.

    Example:
    with mock_now(datetime.datetime(2011, 2, 3, 10, 11)):
    assert datetime.datetime.now() == datetime.datetime(2011, 2, 3, 10, 11)

    Authored by: https://gist.github.com/jimmydo/1113164
    """

    class MockDateTime(datetime.datetime):
        @classmethod
        def now(cls):
            # Create a copy of dt_value.
            return datetime.datetime(
                dt_value.year, dt_value.month, dt_value.day,
                dt_value.hour, dt_value.minute, dt_value.second, 
dt_value.microsecond,
                dt_value.tzinfo
            )
    real_datetime = datetime.datetime
    datetime.datetime = MockDateTime
    try:
        yield datetime.datetime
    finally:
        datetime.datetime = real_datetime


Status model like:

class Status(models.Model):
    created = models.DateTimeField(_('created'), auto_now_add=True)
    timestamp = models.DateTimeField(_('timestamp'), db_index=True)
    (...)


And finally code that uses the above:

with mock_now(datetime.datetime(2013, 03, 07, 23, 0, 9)):
     period = datetime.timedelta(minutes=24*60)
     when = datetime.datetime.now() - period
     print 'when: ', repr(when)

     stats = Status.objects.filter(timestamp__gt=when)
     print 'stats: ', stats


that prints
>>> when:  datetime.datetime(2013, 3, 6, 23, 0, 9)
>>> stats:  [<Status: 2013-03-06 20:00:09 | 1 | True>, <Status: 2013-03-06 
23:30:09 | 1 | False>, <Status: 2013-03-06 23:40:09 | 1 | True>, <Status: 
2013-03-07 06:00:09 | 1 | False>, <Status: 2013-03-07 12:00:09 | 1 | True>]

As you see the first Status is 2013-03-06 20:00:09 (it's 
status_object.timestamp printed here) that shouldn't be included in results 
because 2013-03-06 20:00:09 is less than 2013-03-06 23:00:09


At the same time this works as expected;

with mock_now(datetime.datetime(2013, 03, 07, 23, 0, 9)):
     # when isn't calculated here
     when = datetime.datetime(2013, 03, 07, 23, 0, 9)
     print 'when: ', repr(when)

     stats = Status.objects.filter(timestamp__gt=when)
     print 'stats: ', stats

printing:
>>> when:  MockDateTime(2013, 3, 6, 23, 0, 9)
>>> stats:  [<Status: 2013-03-06 23:30:09 | 1 | False>, <Status: 2013-03-06 
23:40:09 | 1 | True>, <Status: 2013-03-07 06:00:09 | 1 | False>, <Status: 
2013-03-07 12:00:09 | 1 | True>]

when is MockDateTime here and not just datetime.datetime


As well as this works:
# no 'with' here
period = datetime.timedelta(minutes=24*60)
when = datetime.datetime.now() - period
print 'when: ', repr(when)

stats = Status.objects.filter(timestamp__gt=when)
print 'stats: ', stats

printing:
>>> when:  datetime.datetime(2013, 3, 6, 23, 0, 9)
>>> stats:  [<Status: 2013-03-06 23:30:09 | 1 | False>, <Status: 2013-03-06 
23:40:09 | 1 | True>, <Status: 2013-03-07 06:00:09 | 1 | False>, <Status: 
2013-03-07 12:00:09 | 1 | True>]


The problem is that the code that I'm going to test does:
when = datetime.datetime.now() - period what causes filter to return 
unfiltered results. Any ideas on how to solve that?

Best regards
Jakub

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to