Оценка того, стоит ли сначала писать модульный тест или интеграционные тесты в проектах blue-sky / prototype

11

Что-то, что я недавно заметил, это когда я делаю следующие типы проектов:

  • Когда начинается проект
  • Работа над MVP / прототип
  • Добавление функций, которые не определены полностью
  • Работа над меньшим проектом

Для справки, сейчас я работаю над проектом Python, который в настоящее время имеет ~ 1 тыс. Строк кода, включая некоторые комментарии и все пробелы.

Я нахожу, что гораздо проще сначала написать интеграционные тесты, работать над кодом, а затем, как только API немного укрепится, фактически работать над добавлением модульных тестов. Типы тестов, которые я могу запускать main, так сказать, в своей функции, и являются более "сквозными", чем что-либо еще.

Это потому, что модульные тесты действительно раздражают, когда API меняется довольно быстро, что часто бывает при работе над проектом, соответствующим любому или большинству критериев, указанных выше.

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

enderland
источник
6
Делай все, что лучше для тебя. Не слушайте людей, которые говорят, что вы должны работать определенным образом, чтобы быть эффективными: вы знаете, когда вы работаете, а когда нет. Пишете ли вы сначала интеграционные тесты или сначала юнит-тесты, на самом деле не имеет значения. Для некоторых проектов один способ может быть проще, а для других - другой. То, что вы описываете, может быть разницей между дизайном сверху вниз и снизу вверх. И то, и другое полезно, но, как правило, сверху вниз создает лучший дизайн.
Фрэнк Хилман
@FrankHileman действительно, это мой подход. Но так как мне любопытно, я хочу убедиться, что я делаю правильный подход на случай, если я что-то упустил.
enderland
Сначала сфокусируйтесь на спецификациях: части без кода. Каковы инварианты системы? При этом вам может понадобиться сначала выяснить низкий уровень или сначала высокий уровень. Это зависит от того, где находятся наиболее критичные или рискованные алгоритмы. Попробуй убрать это с дороги первым. Это базовое управление рисками.
Фрэнк Хилман
1
В случае работы с прототипом, это нормально, не писать тесты вообще. Цель прототипа - проверить работоспособность идеи. Реализация прототипа поможет определить ожидаемый дизайн приложения.
Фабио,
Это называется снаружи-в разработке. Вы можете проверить следующую книгу, которая делает именно то, что: amazon.com/dp/0321503627
Eternal21

Ответы:

7

Я упускаю значение модульного тестирования подобных проектов, прежде чем API-интерфейсы станут более надежными?

Нет . Ты молодец.

Две большие цели TDD:

  • Определение интерфейсов по фактическому использованию, а не по внутренней реализации 1
  • Максимизация тестового покрытия

Тестовое покрытие может быть довольно хорошо увеличено в любом случае. То есть, независимо от того, тестируете ли вы вначале маленькие , изолированные блоки или большие , «интегрированные» блоки, у вас есть возможность написать свои тесты до реализации.

Первое, что вы получаете, когда пишете тесты более высокого уровня («интеграция»), как вы это делаете, - это уверенность в том, что ваши интерфейсы и взаимодействия более высокого уровня также определяются в первую очередь в зависимости от их использования, а не от их внутренних реализаций.

Тот же самый эффект может быть в значительной степени достигнут с некоторой хорошей "архитектурой" и построением диаграмм. Но эти высокоуровневые тесты часто могут выявить то, что вы пропустили в своих диаграммах - или что вы просто ошиблись в своей работе по «архитектуре».


Если вы на самом деле не делаете TDD (или что-то подобное), порядок написания тестов не имеет большого значения. Интерфейсы уже существуют к тому времени, когда вы тестируете, поэтому гораздо менее вероятно, что ваши тесты изменят что-либо - они будут служить только для защиты от определенных критических изменений.

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


1. Это также применимо, даже если вы не делаете полный TDD. Даже если вы просто пишете 1 или 2 теста до реализации, эти 1 или 2 теста могут помочь вам определить или улучшить ваши интерфейсы, пока не стало слишком поздно!

svidgen
источник
1

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

Когда каждый модульный тест представляет собой просто модификацию, трудно научиться делать его гибким. Они, как правило, не более чем регрессионные тесты. Поскольку вы никогда не использовали их для рефакторинга, очень легко написать тесты, которые на самом деле затрудняют рефакторинг. Это имеет тенденцию выходить из-под контроля, пока вы не потеряете всю веру в TDD.

Тем не менее, вы уже работаете над чем-то. Я не собираюсь говорить тебе останавливаться. Я скажу, что это может стоить того, чтобы начать что-то еще, что у вас есть время, чтобы исследовать и следовать циклу красно-зеленого рефакторинга с самого начала. Убедитесь, что вы действительно используете тесты для рефакторинга. Пока вы не освоите этот способ работы, используйте его экономно на чем-то важном. Это совершенно другой способ написания кода, к которому нужно привыкнуть. Делать это на полпути никому не поможет.

Что сказал

Я нахожу, что гораздо проще сначала написать интеграционные тесты, работать над кодом, а затем, как только API немного укрепится, фактически работать над добавлением модульных тестов. Типы тестов, которые я могу запускать, так сказать, в своей основной функции, и являются более "сквозными", чем что-либо еще.

Поймите, что модульный тест НЕ является просто тестом, который действует на один класс. Пока API, над которым вы работаете, можно тестировать, не выполняя ни одного из следующих действий, вы прекрасно выполняете модульное тестирование:

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

Майкл Фезерс: набор правил модульного тестирования

Так что если ваш сквозной тест включает более одного объекта, это нормально. Это модульное тестирование, а не объектное тестирование.

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

candied_orange
источник