То, что вы делаете, не является модульным тестом . Модульные тесты должны выполнять небольшой «блок» вашего кода и только ваш код. Включая системное время, вы также тестируете среду, в которой вы работаете. Это системный тест . Модульные тесты являются очень эффективными инструментами для проверки правильности написанного вами кода, но это помогает многим из вас писать свой код в «тестируемом» виде.
Есть несколько трюков, которые легко освоить, но трудно освоить, которые помогут вам написать тестируемый код. Как правило, все они следуют одному и тому же шаблону создания в вашем коде того, что они называют «швами», а затем вводят « заглушки » или « макетные объекты » в эти швы во время тестирования. *
Первое, что нужно выяснить, это то, куда идут ваши швы. Это не так сложно. По сути, каждый раз, когда вы строите новый объект, это хорошее место для шва. Обязательным условием для этого правила является то, что у вас есть довольно приличный объектно-ориентированный дизайн для начала. (Ребята из Google Testing Blog утверждают, что вы не можете выполнить модульное тестирование императивный код , потому что вы не можете внедрение зависимостей .) Другое хорошее место для шов - это всякий раз, когда вы общаетесь с внешним источником данных, таким как операционная система, файловая система, база данных, Интернет и т. д. Это то, что вы делаете.
Вам нужно системное время. Вот где ваш шов должен идти. Я рекомендую вам хорошую книгу по этому вопросу для полного рассмотрения всех ваших вариантов здесь, но вот один пример того, что вы могли бы сделать. Есть как минимум 2 или 3 других способа «вставить вашу зависимость» в текущее системное время. Я буду использовать Python для псевдокода, но он работает на любом языке OO:
class MyClass(object):
def _get_current_time(self):
'''This is a test seam'''
return datetime.datetime.now()
def age(self):
return self._get_current_time() - self._birthday
Затем в вашем тестовом коде сделайте следующее:
class FakeMyClass(MyClass):
def __init__(self, test_time, *args, **kwargs):
self._test_time = test_time
MyClass.__init__(self, *args, **kwargs)
def _get_current_time(self)
return self._test_time
Теперь, если вы тестируете с FakeMyClass
, вы можете ввести любое системное время, какое захотите:
myclass = FakeMyClass(t)
self.assertEqual(myclass.age(), expected_age)
Опять же, это довольно большая тема, поэтому я рекомендую приобрести хорошую книгу.