Что делать, если новая функция приводит к тому, что существующие модульные тесты становятся недействительными?

Я создаю новое приложение и стараюсь придерживаться "теста-первого" развития так же верно, как только могу. Я нахожусь в ситуациях, когда мне нужно реализовать/изменить функцию, которая имеет эффект аннулирования ряда существующих модульных тестов. Как мне с этим бороться? Как я вижу, есть 3 варианта:

  • Обновите или удалите все существующие тесты в соответствии с новыми требованиями к функциям (добавив больше по мере необходимости), затем выполните функцию

  • Сначала выполните эту функцию, запустите тесты, чтобы увидеть сбои, и обновите или удалите все неудавшиеся тесты (добавив больше, если необходимо)

  • Добавьте новые тесты для новой функции, реализовать эту функцию, выполнить все тесты чтобы увидеть, как старые из них выходят из строя, удаляют или обновить старые тесты по мере необходимости

Первый вариант относится к TDD, но может быть мучительно контрпродуктивным. Второй вариант - самый простой, но вы не будете точно тестировать сначала и, возможно, не будете должным образом "покрыты". Третий вариант - это компромисс между обоими и привлекательный до определенной степени, но вы рискуете повторно написать тест, когда можете просто обновить старый.

Я не чувствую, что у меня есть четкая стратегия. Что вы делаете в этих ситуациях?

Ответ 1

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

Ответ 2

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

Ответ 3

Реализация функции включает в себя запись/обновление модульных тестов; что является основополагающим для разработки, основанной на испытаниях. Таким образом, ваши второй вариант - это TDD, а не только ваш первый. На практике я подозреваю, что вам понадобится третий вариант с некоторыми модами:

  • Напишите тесты для этой функции (так как это поможет вам проверить ваш API/UI для нее)
  • Напишите функцию
  • Просмотрите модульные тесты в этой общей области, чтобы увидеть те, которые должны сломаться
  • Запустите тесты
  • Исправьте те, которые сломаются, и если в списке есть список из 3, который не сломался, исправьте их (они должны были сломаться). Если кто-либо нарушил, что вы не идентифицировали, исследуйте, чтобы убедиться, что это действительно правильно - исправьте тест или функцию по мере необходимости.
  • Прибыль; -)

Ответ 4

Я думаю, что все подходы разумны. Вы получите тот же результат.

Некоторые люди любят более мелкие шаги и больше работают в оригинальном намерении TDD: напишите строку теста, напишите строку кода, чтобы исправить ее, повторите. Если это вы, сначала поработайте над своими старыми тестами, эволюционируя или удалив их в новую систему.

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

Может быть, действительно зависит от вашего уровня комфорта и уверенности.

Я бы предпочел бы, что в идеале одно изменение должно только разорвать один тест, поэтому вы можете захотеть реорганизовать тестовый код, чтобы это было ваше поведение. Решением может быть какой-то общий метод настройки.

Ответ 5

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

Тесты там, чтобы поддержать то, что вы пытаетесь выполнить, и не должны работать против вас.

Ответ 6

Думаю, здесь есть две вещи. И я не знаю, думаете ли вы об одном или обоих.

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

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