Модульное тестирование: Имеет ли смысл тестировать методы родительского объекта?

#python #django #unit-testing #tdd

#python #django #модульное тестирование #tdd

Вопрос:

Допустим, я использую фреймворк, в котором есть класс с именем Animal.

 class Animal(object):
    def speak(self):
        logging.info(self.sound)
  

Я должен подклассировать этот объект, чтобы использовать его, и это может выглядеть примерно так:

 class Dog(Animal):
    def __init__(self):
        self.sound = 'Woof Woof'
  

На мой взгляд, я мог бы сделать две вещи. Первый — это что-то вроде этого:

 dog = Dog()
assert dog.sound == 'Woof Woof'
  

Второй вариант — макетировать logging.info и проверьте, был ли он вызван. У меня смешанные чувства по поводу них обоих.

В первом случае кажется, что я просто тестирую свою конфигурацию, а во втором — что я на самом деле не тестирую нужный мне объект.

Я использую этот простой пример, потому что, возможно, тогда люди, которые не используют Django, могли бы дать мне несколько советов. Настоящая проблема, с которой я сталкиваюсь, связана с общими представлениями Django.

Например, у меня может быть этот шаблон просмотра:

 class HomeView(TemplateView):
    template_name = 'home.html'
  

Мне просто проверить, имеет ли template_name правильное значение, или я использую тестовый клиент для выполнения теста более высокого уровня для проверки полного представления?

Ответ №1:

Нет, убедитесь, что родительский объект протестирован должным образом (при необходимости с издевательством) и протестируйте методы подобъектов отдельно. Это соответствует концепции инкапсуляции (делает вопросы локальными).

Если вы этого не сделаете, большой проект со многими классами истощит все ваши ресурсы для кодирования без дополнительной пользы.

Комментарии:

1. Итак, вы говорите, что я должен делать оба?

2. @Pickels: Да. Протестируйте родительский и дочерний объекты отдельно.

3. Я начал отвечать на вопрос, но меня вытащили. Я согласен с вашим ответом, но только для упрощения. Можно ли перефразировать ваш вопрос следующим образом: должен ли я тестировать функциональность, производную от родительского класса, когда мы проводим модульное тестирование дочернего класса.? Если я правильно понимаю, то вам нужно убедиться, что все ваши компоненты протестированы. Итак, подготовьте тестовый пример для родительского класса и тестовый пример для дочернего класса. вам не нужно тестировать родительскую функциональность в дочернем, если только вы не перегружаете функциональность.

4. @Pickels да, отдельно, но не проводите повторное тестирование родительского объекта в дочернем (ненужная дублирующая работа).

5. Итак, просто для ясности. Мне нужно убедиться, что оба объекта протестированы правильно? Но если родительский объект принадлежит фреймворку, который, как я полагаю, тщательно протестирован, означает ли это, что мне не нужно тестировать его самому? Просто удостоверяюсь, потому что я получаю смешанные ответы.

Ответ №2:

В вашем простом примере я бы, вероятно, протестировал родительский метод. Но в вашем случае с Django это означало бы тестирование Django. И это не ваша работа! 😉 Для меня это одна из больших проблем модульного тестирования: не тестировать чужой код или библиотеки 3-й части. Убедитесь, что ваша часть верна. Может показаться очевидным, но в реальной жизни это не так просто — по крайней мере, по моему опыту.

Ответ №3:

Тест, который вы показываете, абсолютно правильный — вы повторяете строковый литерал 'Woof Woof' в своем тесте.

Вы могли бы провести аналогичный тест для Animal :

 animal = Animal()
animal.sound = 'sound'
animal.speak()
# test that detects log contains 'sound'
  

У вас также может быть тест, который берет список животных, например [Dog, Cat, ...] , и обнаруживает, что экземпляр каждого из них произносит свой звук.

 for animalClass in AnimalList:
    animal = animalClass()
    animal.speak()
    # test that detects log contains animal.sound