2009-08-18 2 views
11

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

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

  • Реализовать особенность первых, запускать тесты, чтобы увидеть неудачи, обновление или удаление любых неудачных тестов (добавление больше по мере необходимости)

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

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

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

+0

Это то, что я делаю, когда думаю обо всем коде, который я тестировал, который, в конце концов, попал в мусорную корзину: http://www.youtube.com/watch?v=tgBI3-q5COM – Will

+2

Звучит странно, что одно изменение (правильно) может сломать несколько модульных тестов. Может быть, один или два, но несколько? Возможно ли, что ваши тесты устройств слишком много перекрываются? – Beta

+0

@Beta. Скажем, вы добавляете требование о том, что для реализации теперь требуется дополнительный зависимый класс. Теперь ваши другие тесты не обеспечивают ложную реализацию зависимого объекта, поэтому при запуске вы получаете кучу нулевых опорных исключений. Затем вам нужно будет вернуться и исправить свой настроенный код, чтобы потом они прошли. – tvanfosson

ответ

8

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

4

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

4

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

  1. писать тесты для функции (так как это поможет вам проверить ваш API/интерфейс для него)
  2. Написать Функция
  3. Обзор модульные тесты в этой общей области, чтобы увидеть те, которые должны сломать
  4. Выполнить тесты
  5. Фикс те, которые ломаются, и если есть какие-либо в списке из # 3, которые не ломаются, их исправить (они должны иметь сломаны). Если кто-то сломал, что вы не идентифицировали, исследуйте, чтобы убедиться, что это действительно правильно - исправьте тест или функцию по мере необходимости.
  6. Profit ;-)
0

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

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

0

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

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

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

1

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

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

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

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

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

Смежные вопросы