Как выполнить модульное тестирование функций на основе времени без добавления параметров - PullRequest
0 голосов
/ 02 июня 2018

Я создал функцию, которая возвращает секунды, оставшиеся до следующего появления того времени, но я столкнулся с проблемой написания для нее модульного теста.Как люди тестируют функцию такого типа, в которой есть вызов datetime.now()?

Добавление другого параметра (current_time) кажется неправильным только для его проверки, поскольку оно изменяет начальные требования функции.

Функция для проверки:

from datetime import datetime, time, timedelta

def get_time_left(target_time):
    '''return float of number of seconds left until the target_time'''

    if not isinstance( target_time, time ):
        raise TypeError("target_time must be datetime.time")

    curr_time = datetime.now()
    target_datetime = datetime.combine( datetime.today(), target_time )
    if curr_time > target_datetime:
        target_datetime = curr_time + timedelta(1)

    seconds_left = (curr_time - target_datetime).total_seconds()

    return seconds_left

Тест для него:

class TestDTime(unittest.TestCase):

    def test_time_left(self):
        dt_now = datetime.now()
        tm_5sec_future = ( dt_now + timedelta(0,5) ).time()
        self.assertEqual( dtime.get_time_left(tm_5sec_future), 5.0)

Результат:

======================================================================
FAIL: test_time_left (__main__.TestDTime)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/ctatest.py", line 37, in test_time_left
    self.assertEqual( dtime.get_time_left(tm_5sec_future), 5.0)
AssertionError: -4.999985 != 5.0

Каков наилучший подход к модульному тестированию чего-то подобного без добавления аргументов в функцию?

1 Ответ

0 голосов
/ 03 июня 2018

Вам необходимо использовать среду моделирования для изоляции вашего UT от зависимостей, чтобы ваш UT имел согласованное поведение.

Freezegun - это хорошая библиотека для проверки времени, которую я использовал.

Просто установите эту библиотеку: pip install freezegun

В вашем UT использовался декоратор @freeze_time в качестве следующего:

@freeze_time("2018-06-03") 
def test_time_left(self):
    dt_now = datetime.now()
    tm_5sec_future = (dt_now + timedelta(0, 5)).time()
    self.assertEqual(dtime.get_time_left(tm_5sec_future), -5.0)
...