Как использовать макет для проверки функции next_day_of_week - PullRequest
9 голосов
/ 05 июля 2011

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

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

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

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

Поэтому я пытаюсь смоделировать datetime.date в тестах.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)

И я создаю свой тестовый пример, внося исправления в класс mock и устанавливая сегодня на 3/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:

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

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

Ответы [ 2 ]

10 голосов
/ 05 июля 2011

Разобрался.

Вопрос был действительно Куда патчить , и ответ пришел после изучения Mock документации, на которую я ссылался выше (эта страница) .

Решением было макетирование класса date в пространстве имен модуля, который содержит модели для этого приложения, например:

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

    # mock out the date class in the module that has already imported it via
    # from datetime import date, i.e. series.models (app_name.module_name)
    @mock.patch('series.models.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))

Надеюсь, это может помочь кому-то еще!

0 голосов
/ 05 июля 2011

Я думаю, что нужный вам ответ содержится в другом посте . Я переписал в соответствии с вашими потребностями.

import datetime
class FakeDate(datetime.date):
    @classmethod
    def today(cls):
        return cls(2011, 7, 3)
datetime.date = FakeDate

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

    def test_valid_my_next_day_of_week_sameday(self):
        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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...