Пытаясь получить уверенность в преимуществах TDD

Я только что купил Искусство тестирования единиц от Amazon. Я очень серьезно отношусь к пониманию TDD, поэтому будьте уверены, что это настоящий вопрос.

Но я чувствую, что я постоянно на пороге нахождения оправдания, чтобы отказаться от него.

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

1. TDD для уменьшения ошибок

Этот часто цитируемый пост в блоге говорит, что модульные тесты - это инструменты проектирования, а не для обнаружения ошибок:

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

...

TDD - это надежный способ проектирования программные компоненты ( "единицы" ) интерактивно, чтобы их поведение определяется посредством модульных испытаний. Вот и все!

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

Достаточно справедливо, сокращение ошибок - это не единственное, с чем должно помочь TDD.

2. TDD как парадигма дизайна

Это, вероятно, большой. TDD - это парадигма дизайна, которая помогает вам (или заставляет вас) сделать ваш код более составным.

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

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

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

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

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

3. TDD как документация

TDD, как говорят, служит документацией, но он служит только документацией для сверстников; потребитель по-прежнему требует текстовой документации.

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

Хороший unit test будет описывать в своей сигнатуре метода точное поведение, которое проверяется, и тест будет проверять не более того и не меньше этого поведения.

Итак, я бы сказал, ваше время может быть лучше потрачено на полировку вашей документации. Черт, почему бы не сделать только документацию в первую очередь и назвать ее Documentation-Driven Design?

4. TDD для регрессионного тестирования

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

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

Ответ 1

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

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

Ответ 2

С точки зрения дизайна, один из основных преимуществ TDD, который вы не видите, заключается в том, что он просто заставляет дизайн. Вы знаете, что говорят, что инженер видит стекло вдвое больше, чем должно быть. Переописание программного обеспечения может быть большой проблемой. Я нахожу, что 90 +% времени TDD вытеснили правильное соотношение абстракции, чтобы поддерживать последующее расширение кода. TDD не является волшебным, для этого требуется программист, но это важная часть инструментария.

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

Кроме того, вы пишете: "Итак, не имеет смысла писать блок-тесты по мере необходимости, когда код изменяется, сохраняя старый код и сравнивая его результаты с новой функцией?" Код, который написан без учета модульного тестирования, часто не тестируется, особенно если он взаимодействует с внешними службами, такими как база данных, менеджер транзакций, инструментарий GUI или веб-сервис. Добавление их позже просто не произойдет.

Я думаю, что Боб Мартин сказал, что это лучше всего, TDD - это программирование того, что Double Entry относится к учету. Это предотвращает определенный класс ошибок. Это не мешает всем проблемам, но обязательно убедитесь, что если ваша программа намеревалась добавить два плюс два, они вместо этого не вычтут их. Важное значение имеет основное поведение, и, когда это происходит не так, вы можете потратить много времени на поиск своего отладчика.

Ответ 3

TDD - это не методология, это мышление.

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

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

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

Ответ 4

Я просто хотел подчеркнуть:
Тесты TDD не являются модульными тестами

"Цель unit test - проверить единицу кода в изоляции".
"Тест TDD, в отличие от unit test, может тестировать более чем одну единицу кода за раз". TDD Tests больше тестов взаимодействия....

от Стивена Уолтера очень хорошее сообщение в блоге Тесты TDD не являются модульными тестами

Ответ 5

В Javascript или на любом языке, который должен работать в нескольких причудливых средах, таких как браузеры, модульные тесты - отличный способ сказать , где Internet Effing Explorer перепутал, что исправить.

По крайней мере, это лучше, чем забивать F5 и использовать console.log() или даже предупреждения.

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

Если вы напишете следующий jQuery, модульные тесты станут вашими друзьями!:)

О, и не забудьте отличные инструменты для js, например JSTestDriver!

Ответ 6

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