2017-02-01 52 views
5

Piszę tutaj test funkcjonalny, aby sprawdzić, czy moje ograniczanie API działa zgodnie z oczekiwaniami (będzie odpoczywać na początku każdego miesiąca).Problem z szyderstwem w teście django: czas wydaje się nie być zamrożony za pomocą freezegun

Testowanie Klasa:

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) 

Test działa prawidłowo gdy: last_day_of_current_month = datetime.datetime(... second=0)
ale nie powiedzie się, jeśli: last_day_of_current_month = datetime.datetime(... second=59)

Po debugowanie wydaje się, że moduł time stosowanych w DjangoRestFramework throttling.UserRateThrottle w jakiś sposób daje wartość, która zawsze wyprzedza czas fronzen w moim teście, który wynosi ca używając precyzyjnego wydania o kilku sekundach.

podstawie FreezeGun Doctime.time() powinny być również mrożone:

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.

Ale wygląda na to im mój przypadek time.time wykonuje poprawnie czas rozpoczęcia wyśmiewali datetime ale potem zmieniają się w czasie, który nie ma, to się tego spodziewać zamrożone do czasu ręcznego przekazania dalej.

Próbowałem wyśmiać time.time używany w UserRateThrottle oddzielnie przy użyciu modułu mock, ale nadal nie rozwiązałem problemu.

----> Jakiś pomysł, jaki może być problem i jak można go rozwiązać?

test Fail: (po raz jest przekazywany do ostatniego dnia miesiąca: linii 14)

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

Kod źródłowy klasy 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 
     .... 

Odpowiedz

0

musisz zastąpić timer SimpleRateThrottle za pomocą FreezeG un's time.time.

W tym przypadku feezegun prawdopodobnie zastąpi moduł czasu Pythona. Jednak SimpleRateThrottle nie korzysta z modułu, korzysta z funkcji modułu, która staje się poza zasięgiem pistoletu do zamrażania.

SimpleRateThrottle używa zatem modułu czasu standardowej biblioteki Python, podczas gdy inna część kodu korzysta z modułu freezegun.

Edit: Powinieneś to zrobić - po FreezeGun został aktywowany:

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

i raz Twój test jest nad (w przerywaniem czy cokolwiek równoważne):

SimpleRateThrottle.timer = former_timer 

pamiętać, że może również użyj łatki do łatania małp, aby poradzić sobie z tym za ciebie.

+0

Jak mogę zmienić to za pomocą FreezeGun !? W rzeczywistości pomyślałem o tym i próbowałem wyśmiać zwróconą wartość funkcji modułu używanej przez 'SimpleRateThrottle' ręcznie przy użyciu łatki małpy przy użyciu modułu python' mock', ale nadal mam ten sam problem !!! – DhiaTN

+1

Przepraszam, uświadomiłem sobie, że po napisałem odpowiedź. Teraz jest edytowane z tym, jak to zrobić. – Linovia

+0

Dzięki, ale nadal masz ten sam problem. – DhiaTN