Как использовать имитацию для тестирования функции next_day_of_week

Я отслеживаю события, которые повторяются в определенный день недели (например, первое воскресенье месяца, третью пятницу месяца). У меня есть модель DayOfWeek, в которой хранится день недели события. Он содержит метод next_day_of_week для возврата объекта даты, установленного для следующего наступления любого дня недели, установленного для данного экземпляра события (это помогает выяснить, когда наступит следующее наступление события).

Например, в воскресенье 7/3/2011:

  • Для объекта с DayOfWeek, установленным на воскресенье, next_day_of_week вернет 7/3/2011.
  • Для DayOfWeek, установленного на понедельник, возвращается 7/4/2011.
  • Для DayOfWeek, установленного на субботу, будет возвращено 7/9/2011.

И так далее. Я пишу модульные тесты (мои первые тесты; я уже упоминал, что я новичок в этом деле?) И пытаюсь понять, как протестировать этот метод. Я знаю, что мне нужно поиздеваться над чем-то, но я не совсем понимаю над чем. Этот вопрос, кажется, объясняет то, о чем я спрашиваю: Python: пытаюсь высмеять datetime.date.today (), но не работает

Поэтому я пытаюсь высмеять datetime.date в tests.py:

class FakeDate(date):
"A fake replacement for date that can be mocked for testing."
    def __new__(cls, *args, **kwargs):
        return date.__new__(date, *args, **kwargs)

И я создаю свой тестовый пример, исправляя макет класса и устанавливая сегодня на 7/3/2011:

class TestDayOfWeek(TestCase):
    """Test the day of the week functions."""

    @mock.patch('datetime.date', FakeDate)
    def test_valid_my_next_day_of_week_sameday(self):
        from datetime import date
        FakeDate.today = classmethod(lambda cls: date(2011, 7, 3)) # July 3, 2011 is a Sunday
        new_day_of_week = DayOfWeek.objects.create()
        new_day_of_week.day = "SU"
    self.assertEquals(new_day_of_week.my_next_day_of_week(), date(2011, 7, 3))

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

class DayOfWeek(ModelBase):
"""
Represents a day of the week (on which an event can take place). 
Because the dates of these events are often designated by terms like 'first Monday'
or 'third Friday', this field is useful in determining on which dates individual
readings take place.
"""

# The pk in the db is 1-indexed (Monday=1, Tuesday=2, etc), but python's days 
# of the week are 0-indexed if you use .weekday(), so we are using .isoweekday()
# instead. This list is used in my_next_day_of_week.
days =[ 'No day', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',
       'Sunday' ]

DAYS_OF_WEEK_CHOICES = (
('MO', days[1]),
('TU', days[2]),
('WE', days[3]),
('TH', days[4]),
('FR', days[5]),
('SA', days[6]),
('SU', days[7]),
)

day = models.CharField(max_length=2, choices=DAYS_OF_WEEK_CHOICES)

def __unicode__(self):
    for daypair in self.DAYS_OF_WEEK_CHOICES:
        if self.day in daypair:
            return daypair[1]

    # This shouldn't happen
    raise InvalidDayOfWeekError

# my_next_day_of_week returns a datetime equal to the start (midnight+min) of the next day that is this instance's day of the week.
# It doesn't know what time the event is, so if today is the day of the week the event falls on,
# it simply returns today.
def my_next_day_of_week(self):
    """ 
    Returns a datetime equal to the start of the next day that is this instance's day of the week. 
    """

    today_day = date.today().isoweekday() # Find the number of the current day of the week
    reading_day = self.days.index(self.__unicode__()) # Find the number of the instance's day of the week
            # There is probably a more pythonic way to do this next part
    next_day = date.today() # start with next day = today
    while next_day.isoweekday() != reading_day:
        next_day = next_day + timedelta(1)

    return next_day

Итак, когда я запускаю средство запуска тестов django, тест не проходит, потому что мой Экземпляр DayOfWeek, похоже, не использует фиктивный datetime.date и вместо этого видит текущий день. Из моего чтения я понимаю, что макет существует только в рамках метода тестирования, а не до или после. Но означает ли это, что он не существует для каких-либо объектов / методов, которые создаются / вызываются из тестового метода? Тогда какая от этого польза? Я не думаю, что это проблема, а скорее в том, что я что-то делаю не так при установке патчей. Может проблема с пространствами имен?Я читаю это: http://www.voidspace.org.uk/python/mock/patch.html#id2 Я буду продолжать попытки исправить это и отредактирую это, если мне это удастся, но до тех пор приветствуются любые указатели!

РЕДАКТИРОВАТЬ: Я понял, что я использовал datetime.datetime в своей модели вместо datetime.date. Я исправил это и отредактировал приведенный выше код, но основная проблема неиспользуемого имитационного класса осталась.

9
задан Community 23 May 2017 в 12:34
поделиться