Имитация прохождения времени в unittesting - программирование
Подтвердить что ты не робот

Имитация прохождения времени в unittesting

Я построил систему клиентских платежей CMS + для клиента, и мне нужно получить более строгие результаты при тестировании.

Я сохраняю все свои данные в ORM Django и имею множество задач Celery, которые выполняются с разными интервалами, что гарантирует отправку новых счетов-фактур и напоминаний о счетах и ​​сокращение доступа, когда пользователи не оплачивают свои счета-фактуры.

Например, я хотел бы иметь возможность запускать тест, который:

  • Создает нового пользователя и создает счет за X дней доступа к сайту

  • Имитирует прохождение X + 1 дня и выполняет все задания, которые я установил в Celery.

  • Проверяет, что пользователю был выдан новый счет за другие X дней.

Подход KISS, к которому я придумал, - это все тестирование на отдельной машине и фактическое манипулирование датой/временем на уровне ОС. Таким образом, тестирование script:

  • Установите системную дату на день 1

  • Создайте нового пользователя и сгенерируйте первый счет за X дней доступа

  • Затем введите системную дату 1 день. Запустите все задания по сельдерею. Повторяйте до тех пор, пока X + 1 день не пройдет "

  • Убедитесь, что новый счет выставлен

Это немного неуклюже, но я думаю, что это может сработать. Любые другие идеи о том, как это сделать?

4b9b3361

Ответ 1

Вы можете использовать mock, чтобы изменить возвращаемое значение функции, используемой вами для получения времени (datetime.datetime.now например).

Существуют различные способы сделать это (см. макет документации), но вот один из них:

import unittest
import datetime
from mock import patch

class SomeTestCase(unittest.TestCase):
    def setUp(self):
        self.time = datetime.datetime(2012, 5, 18)
        class fakedatetime(datetime.datetime):
            @classmethod
            def now(cls):
                return self.time
        patcher = patch('datetime.datetime', fakedatetime)
        self.addCleanup(patcher.stop)
        patcher.start()

    def test_something(self):
        self.assertEqual(datetime.datetime.now(), datetime.datetime(2012, 5, 18))
        self.time = datetime.datetime(2012, 5, 20)
        self.assertEqual(datetime.datetime.now(), datetime.datetime(2012, 5, 20))

Поскольку мы не можем напрямую заменить datetime.datetime.now, мы создаем поддельный класс datetime, который делает все одинаково, за исключением возвращения постоянного значения, когда он теперь вызывается.

Ответ 2

Без использования специальной макетной библиотеки я предлагаю подготовить код для макета (возможно, с помощью глобальной переменной). В режиме макета вместо вызова нормальной функции времени (например, time.time() или любого другого) вы можете вызвать функцию времени макета, которая возвращает все, что вам нужно в вашем специальном случае.

Я бы проголосовал за изменение системного времени. Это не похоже на unit test, а скорее как функциональный тест, поскольку он не может выполняться параллельно ни с чем другим на этой машине.