2015-01-13 3 views
1

Итак, я работаю над приложением, которое при импорте определенных записей требует, чтобы некоторые поля были пересчитаны. Чтобы предотвратить чтение базы данных для каждой проверки, есть декодер кеширования, поэтому чтение базы данных выполняется только один раз каждые n секунд во время импорта. Проблема заключается в создании тестовых примеров. Следующее работает, но в нем есть уродливый сон.Выполнение модульных тестов в Python с помощью декоратора кеширования

# The decorator I need to patch 

@cache_function_call(2.0) 
def _latest_term_modified(): 
    return PrimaryTerm.objects.latest('object_modified').object_modified 


# The 2.0 sets the TTL of the decorator. So I need to switch out 
# self.ttl for this decorated function before 
# this test. Right now I'm just using a sleep, which works 

    @mock.patch.object(models.Student, 'update_anniversary') 
    def test_import_on_term_update(self, mock_update): 
     self._import_student() 
     latest_term = self._latest_term_mod() 
     latest_term.save() 
     time.sleep(3) 
     self._import_student() 
     self.assertEqual(mock_update.call_count, 2) 

Сам декоратора выглядит следующим образом:

class cache_function_call(object): 
    """Cache an argument-less function call for 'ttl' seconds.""" 
    def __init__(self, ttl): 
     self.cached_result = None 
     self.timestamp = 0 
     self.ttl = ttl 

    def __call__(self, func): 
     @wraps(func) 
     def inner(): 
      now = time.time() 
      if now > self.timestamp + self.ttl: 
       self.cached_result = func() 
       self.timestamp = now 
      return self.cached_result 
     return inner 

Я попытался установить декоратор до импорта моделей:

decorators.cache_function_call = lambda x : x 
import models 

Но даже в верхней части file, django по-прежнему инициализирует модели перед запуском моего tests.py, и функция по-прежнему украшена декодером кеширования вместо моего lambda/noop.

Каков наилучший способ написать этот тест, чтобы я не спал. Могу ли я установить ttl декоратора перед запуском моего импорта?

ответ

1

Вы можете немного изменить класс декоратора.

На уровне модуля в decorators.py установить глобальную

BAILOUT = False 

и в классе декоратора, изменение:

def __call__(self, func): 
    @wraps(func) 
    def inner(): 
     now = time.time() 
     if BAILOUT or now > self.timestamp + self.ttl: 
      self.cached_result = func() 
      self.timestamp = now 
     return self.cached_result 
    return inner 

Затем в тестах набор decorators.BAILOUT = True, и, вуаля -)

Смежные вопросы