Error starting django test: time does not freeze with freezegun

I am writing a functional test here to check if my API throttling works as expected (there will be a rest at the beginning of each month).

Testing Class:

class ApiThrottlingTest(ThrottlingBaseTest): def test_throttling_purchaser_case(self): now = datetime.datetime(year=2015, month=1, day=10, hour=6, minute=6, second=3) last_day_of_current_month = datetime.datetime(year=2015, month=1, day=31, hour=23, minute=59, second=59) first_day_of_next_month = datetime.datetime(year=2015, month=2, day=1, hour=0, minute=0, second=0) with freeze_time(now) as frozen_datetime: for i in xrange(3): resp = self._project_details_request() self.assertEqual(resp.status_code, 200) resp = self._project_details_request() self.assertEqual(resp.status_code, 429) frozen_datetime.move_to(last_day_of_current_month) resp = self._project_details_request() # the test fails at this level self.assertEqual(resp.status_code, 429) frozen_datetime.move_to(first_day_of_next_month) resp = self._project_details_request() self.assertEqual(resp.status_code, 200) 

The test works fine if: last_day_of_current_month = datetime.datetime(... second=0)
but will fail if: last_day_of_current_month = datetime.datetime(... second=59)

After debugging, it looks like a time module, used in DjangoRestFramework throttling.UserRateThrottle somehow gives a value that is always ahead of the time of my test, which causes some accuracy for several seconds.

Based on FreezeGun, Doc time.time() should also be frozen:

After calling the decorator or context manager, all calls to datetime.datetime.now (), datetime.datetime.utcnow (), datetime.date.today (), time.time (), time.localtime (), time.gmtime () and time.strftime () will return the time that was frozen.

But it looks like my case time.time correctly takes the start time of the mocking time-time, but then continues to change with time, which is not expected, it is expected that it will be frozen until the time is redirected manually.

I tried to mock time.time used in UserRateThrottle seperatly using the mock module, but still didn't solve the problem.

----> Any idea what could be the problem, and how can I solve the problem?

Test failure: (after shipment on the last day of the month: line 14 )

self.assertEqual (resp.status_code, 429)
AssertionError: 200! = 429

Source code for the DRF class :

 class SimpleRateThrottle(BaseThrottle): ... cache = default_cache timer = time.time cache_format = 'throttle_%(scope)s_%(ident)s' def __init__(self): .... def allow_request(self, request, view): ... self.now = self.timer() # here timer() returns unexpected value in test .... 
+5
source share
1 answer

you need to override the SimpleRateThrottle timer with FreezeGun time.time.

What happens here is that payzegun is likely to override the Python time module. However, SimpleRateThrottle does not use a module; it uses a module function, which becomes inaccessible for freezing a gun.

SimpleRateThrottle therefore uses the Python standard library time module, while the rest of the code uses freezegun.

Edit: You have to do - after activating FreezeGun:

 former_timer = SimpleRateThrottle.timer SimpleRateThrottle.timer = time.time 

and after the test is completed (in tearDown or any equivalent):

 SimpleRateThrottle.timer = former_timer 

Please note that you can also use the monkey patch library to handle this for you.

0
source

Source: https://habr.com/ru/post/1263675/


All Articles