2016-08-31 4 views
2

У меня есть класс и последующий метод:Как я могу тестировать метод, используя дату-время?

class DateTimeHelper(object): 

    @staticmethod 
    def get_utc_millisecond_timestamp(): 
     (dt, micro) = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f').split('.') 
     return "%s.%03d" % (dt, int(micro)/1000) # UTC time with millisecond 

Как я могу модульного тестирования это? Я полностью потрясен, хотя это просто. Это мой первый модульный тест.

+0

Мок из 'utcnow' вернуть известную дату и время? – jonrsharpe

+0

Вы можете «высмеять» дату и время: http://stackoverflow.com/questions/4481954/python-trying-to-mock-datetime-date-today-but-not-working. – alecxe

ответ

5

Используйте unittest.mock library (Python 3.3 и новее, с обратной связью как mock), чтобы заменить вызовы на любой код, внешний для вашего кода.

Здесь я бы издеваться не только utcnow() но strftime() тоже просто возвращает объект строки:

with mock.patch('datetime.datetime') as dt_mock: 
    dt_mock.utcnow.return_value.strftime.return_value = '2016-08-04 12:22:44.123456' 
    result = DateTimeHelper.get_utc_millisecond_timestamp() 

Если вы чувствуете, что тестирование strftime() аргумент важно, дать dt_mock.utcnow.return_value явное datetime объекта для возвращение вместо этого; Вы должны были бы создать этот тестовый объект перед тем вы издеваться однако, как вы не можете насмехаться из всего метода datetime.datetime.utcnow класса:

testdt = datetime.datetime(2016, 8, 4, 12, 22, 44, 123456) 
with mock.patch('datetime.datetime') as dt_mock: 
    dt_mock.utcnow.return_value = testdt 
    result = DateTimeHelper.get_utc_millisecond_timestamp() 

или в ваших UnitTests, используйте from datetime import datetime сохранить ссылку на класс, который не издевается.

Демо:

>>> from unittest import mock 
>>> import datetime 
>>> class DateTimeHelper(object): 
...  @staticmethod 
...  def get_utc_millisecond_timestamp(): 
...   (dt, micro) = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f').split('.') 
...   return "%s.%03d" % (dt, int(micro)/1000) # UTC time with millisecond 
... 
>>> with mock.patch('datetime.datetime') as dt_mock: 
...  dt_mock.utcnow.return_value.strftime.return_value = '2016-08-04 12:22:44.123456' 
...  result = DateTimeHelper.get_utc_millisecond_timestamp() 
... 
>>> result 
'2016-08-04 12:22:44.123' 
>>> testdt = datetime.datetime(2016, 8, 4, 12, 22, 44, 123456) 
>>> with mock.patch('datetime.datetime') as dt_mock: 
...  dt_mock.utcnow.return_value = testdt 
...  result = DateTimeHelper.get_utc_millisecond_timestamp() 
... 
>>> result 
'2016-08-04 12:22:44.123' 
+0

Модуль стороннего разработчика [freezegun] (https://github.com/spulec/freezegun) также может быть весьма полезен, а в некоторых случаях - сэкономить время ... (имеет удобные декораторы и контекстные менеджеры) –

+0

'freezegun' производит сложные издевается; Я до сих пор не видел ни одного случая использования, когда вы не могли добиться того же с 'mock'. Поскольку 'mock' является стандартом defacto, я не уверен, что когда-нибудь выберет' freezegun'. –

+0

Я не видел, где я не мог воспроизвести что-либо с помощью 'urllib', что я не мог с' запросами' ... это в основном удобство - вот и все. –

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