TDD и честность теста

Меня беспокоит «честность» теста при выполнении TDD. TDD это

  1. Напишите красный тест
  2. Напишите достаточно кода, чтобы сделать его зеленым
  3. Рефакторинг и пусть тест зеленый

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

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

  1. Напишите красный тест: «[email protected]» отображается внутри default_page.html.
  2. Напишите достаточно кода, чтобы сделать его зеленым: жестко закодируйте «[email protected]» внутри default_page.html.
  3. Рефакторинг путем реализации get_current_user(), некоторого другого кода в некоторых других слоях и т. д., оставив тест зеленым.

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

Что мне здесь не хватает?


person bdavidxyz    schedule 20.10.2014    source источник
comment
Что заставляет вас думать, что жесткое кодирование текста на странице квалифицируется как «Напишите достаточно кода, чтобы сделать его зеленым»? Хотя, конечно, полезно проверить, что тест работает.   -  person T.J. Crowder    schedule 20.10.2014
comment
@ T.J.Crowder, потому что, к сожалению, это чепуха, поддерживаемая известными книгами по TDD.   -  person Oliver Charlesworth    schedule 20.10.2014
comment
@OliverCharlesworth: Ну, как я уже сказал, полезно протестировать тест, что очень важно ...   -  person T.J. Crowder    schedule 20.10.2014
comment
Это правда: эти три шага не охватывают всю разработку программного обеспечения. Они всего лишь ориентиры. Да, вы можете играть в них, как описано, так же, как вы могли бы играть в любой трехэтапный процесс. Просто не делайте этого, и все будет в порядке. Если вы действительно беспокоитесь, что это сделает кто-то другой, вы можете сделать так, чтобы тест случайным образом генерировал разные адреса электронной почты для каждого запуска.   -  person Erin Call    schedule 20.10.2014
comment
@ TJCrowder Я не согласен с тестированием теста. Тест проверяет как себя, так и тестируемый материал.   -  person bdavidxyz    schedule 20.10.2014
comment
@ davidb583 - согласны вы с этим или нет - представьте, что вы жестко запрограммировали адрес на странице, и тест не стал зеленым. Теперь вы можете потратить время на то, чтобы выяснить, почему тест не работает, прежде чем приступить к реальной реализации. Решите ли вы сделать это или нет, может зависеть от жесткости вашего собственного процесса и вашей уверенности в том, что простой тест, безусловно, должен быть правильным.   -  person Damien_The_Unbeliever    schedule 20.10.2014


Ответы (3)


Я бы сказал, что то, что у вас есть, лишь частично завершено. Вы сказали:

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

Тест не проверяет адрес электронной почты текущего пользователя на странице по умолчанию, он проверяет наличие на странице фиксированного адреса электронной почты "[email protected]".

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

Итак, я бы сказал, что у вас есть что-то вроде псевдокода:

Given current user has email address "[email protected]"
When they visit the default page
The page should contain the email address "[email protected]"

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

Given current user has email address "[email protected]"
When they visit the default page
The page should contain the email address "[email protected]"

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

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

Этот подход распространен в TDD и называется триангуляцией.

person Sam Holder    schedule 20.10.2014
comment
Да, но... Множество книг, включая знаменитую amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530/ рекомендует не злоупотреблять триангуляцией. Обычно лучше (и делает тесты более последовательными) рефакторить тесты с помощью триангуляции. Кроме того, случайная генерация имени пользователя — не очень хорошая практика в модульном тестировании (все, что содержит слово random, не должно использоваться в модульных тестах). Тем не менее, хороший ответ +1 - person ethanfar; 21.10.2014
comment
Хорошая мысль о триангуляции. Однако я не уверен, что согласен с «ничего случайного» в тесте. Иногда вам просто нужно значение, не требуя, чтобы оно было чем-то конкретным, а генерация данных «случайным образом» позволяет избежать кодирования решения для тестовых данных. Если вы используете одно и то же начальное число для случайного объекта, вы каждый раз гарантируете получение одних и тех же тестовых данных, несмотря на то, что они генерируются случайным образом. это устраняет опасения по поводу случайного сбоя тестов из-за тестовых данных. AutoFixture — это фреймворк, написанный для предоставления таких данных. - person Sam Holder; 21.10.2014

Ваше утверждение, что "ничего не работает" неверно. Код работает корректно, если адрес электронной почты — [email protected]. И вам не нужен этот окончательный рефакторинг. Ваш следующий неудачный тест может заключаться в том, чтобы сделать его неудачным в случае, если у пользователя другой адрес электронной почты.

person Raedwald    schedule 20.10.2014
comment
+1 ОП находится в середине процесса, и ему нужно добавить больше тестов, чтобы определить точное поведение, которое они хотят - person Sam Holder; 20.10.2014

Вы правы насчет

шаг 2. Здесь что-то не так

но это не подход TDD. ИМХО дело в тестовой логике. После всего этого (шаг 2) подтверждается, что тестовая система работает правильно. Что новый тест не проходит по ошибке без необходимости в новом коде, и что необходимая функция еще не существует.

Что мне здесь не хватает?

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

person ekostadinov    schedule 20.10.2014