J'écris ici un test fonctionnel pour vérifier si ma régulation de l'API fonctionne comme prévu (ce sera le repos au début de chaque mois).Problème de temps de moquerie dans le test django: le temps ne semble pas être gelé avec freezegun
Classe d'essai:
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)
Le test fonctionne bien si: last_day_of_current_month = datetime.datetime(... second=0)
mais échouera si: last_day_of_current_month = datetime.datetime(... second=59)
Après le débogage, il semble que le module time
utilisé dans DjangoRestFramework throttling.UserRateThrottle
est en quelque sorte donner une valeur qui est toujours en avance sur le temps de fronzen dans mon test, qui est ca en utilisant un problème de précision de quelques secondes.
Basé sur FreezeGun Doctime.time()
devrait aussi être congelés:
Once the decorator or context manager have been invoked, 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 has been frozen.
Mais il semble que im mon cas time.time
prend correctement l'heure de début de l'datetime moqué mais ne cessent de changer au fil du temps qui ne devrait pas, il est prévu être congelé jusqu'à ce que l'heure soit transmise manuellement.
J'ai essayé de simuler time.time
utilisé dans UserRateThrottle
séparément en utilisant mock
module mais n'a pas encore résolu le problème.
----> Une idée de ce qui pourrait être le problème, et comment pourrait éventuellement être résolu?
test Fail: (après le temps est transmis au dernier jour du mois: ligne 14)
self.assertEqual(resp.status_code, 429)
AssertionError: 200 != 429
Le code source de la classe DRF:
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
....
Comment puis-je le remplacer avec FreezeGun !? En fait, j'y ai pensé et j'ai essayé de me moquer de la valeur renvoyée de la fonction module utilisée par 'SimpleRateThrottle' manuellement en utilisant le patch de singe en utilisant le module python' mock' mais j'ai toujours le même problème !!! – DhiaTN
désolé, s'est rendu compte qu'après avoir écrit ma réponse. Il est maintenant édité avec un comment. – Linovia
Merci, mais ont toujours le même problème. – DhiaTN