Лучшая практика юнит тестирования юнитов

29

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

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

Мне просто интересно, если кто-нибудь может дать хороший совет:

  1. Должен ли я смотреть на модульное тестирование в начале проекта и, возможно, принять подход TDD.
  2. Должен ли я просто написать тесты, как я иду, после того, как каждый раздел завершен.
  3. Должен ли я завершить проект, а затем написать модульные тесты в конце.
wilhil
источник
1
Связанный: ( programmers.stackexchange.com/questions/10849/… )
Беофетт
1
Связанный: programmers.stackexchange.com/questions/41196/…
dietbuddha

Ответы:

29

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

Прежде всего, нужно написать несколько юнит-тестов. Сначала они не должны быть идеальными. Просто научите себя, как тестировать небольшие блоки кода и как использовать макеты для изоляции компонентов.

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

Для меня большим моментом Eureka было приложение для Windows, где я пытался протестировать регулярное выражение, которое требовало от меня заполнить две формы, прежде чем я смог добраться до него. Я установил NUnit и написал тест для этого метода и увидел, как быстро я сэкономил часы тестирования. Затем я добавил больше тестов для решения крайних случаев. И так далее.

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

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

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

прецизионный самописец
источник
+1 Спасибо - оставив открытым некоторое время в случае других ответов, но я думаю, что этот проект станет для меня поворотным моментом на тех же основаниях - несколько веб-страниц, и ручное тестирование займет намного больше времени.
wilhil
@pdr у тебя есть какие-то ссылки, которые я могу изучить на тему «хорошо писать модульные тесты»?
Гастон
9

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

Мой ответ однозначный да. Я изучил подход TDD около 10 лет назад, после такого же количества времени программирования без тестов. В наши дни, если я делаю что-то короткое (<250 loc) и простое, или что-то одноразовое, то я не буду использовать TDD. В противном случае я делаю, и именно потому, что это экономит время.

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

Однако чем меньше страха, тем он тоньше. Пока вы не проведете некоторое время в кодовой базе TDD, вы даже не поймете, сколько времени вы тратите, заботясь об изменениях, которые вы делаете. X работает? Это сломает Y? Есть ли некоторые Z, которые могут быть затронуты? С TDD это исчезает, потому что вы превращаете свои страхи в тесты, а затем компьютер автоматизирует беспокойство. Храбрый разработчик - более быстрый разработчик.

Уильям Пьетри
источник
1
+1 за меньший страх. И на этой неделе я проводил рефакторинг кода без тестов. , ,
Уайет Барнетт
2
Отличная цитата: «Вы превращаете свои страхи в тесты, а затем компьютер автоматизирует беспокойство»!
RichVel
5
  1. Должен ли я смотреть на устройство в начале и принять подход TDD.

  2. Должен ли я просто писать тесты по мере выполнения каждого раздела.

Любой из них, но не третий вариант .

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

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

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

Петер Тёрёк
источник
Я думаю, что я буду идти по второму варианту, основываясь на ваших и рекомендации PDR - для третьего варианта я действительно имел в виду, что буду проводить ручное тестирование и просто писать тест в конце, чтобы убедиться, что все выполнено так, как должно быть, и проверить, были ли какие-либо изменения в будущем.
wilhil
2

Я думаю, что для новичка лучше всего использовать некоторые кодовые каты, пригодные для модульного тестирования. Например; проверка адреса электронной почты. TDD становится естественным потоком после того, как вы справитесь с некоторыми из этих кодовых катасов. Проверьте следующий код Kata для валидатора адреса электронной почты, о котором я упоминал: E-mail Validator

Чтобы узнать, что такое Code Katas для тех, кто не знает, перейдите по следующей ссылке: Code Katas

Аниш Патель
источник