Что такое юнит-тестирование? - PullRequest
204 голосов
/ 04 августа 2008

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

  • Что это?
  • Что это делает для меня?
  • Зачем мне его использовать?
  • Когда я должен использовать это (также, когда нет)?
  • Какие распространенные ошибки и заблуждения

Ответы [ 20 ]

194 голосов
/ 04 августа 2008

Модульное тестирование - это, грубо говоря, тестирование битов вашего кода изолированно с тестовым кодом. Непосредственные преимущества, которые приходят на ум:

  • Выполнение тестов становится автоматизируемым и повторяемым
  • Вы можете тестировать на гораздо более детальном уровне, чем тестирование методом "укажи и щелкни" с помощью графического интерфейса пользователя

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

Другой способ взглянуть на модульное тестирование - сначала написать тесты. Это известно как разработка через тестирование (для краткости TDD). TDD приносит дополнительные преимущества:

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

Если вы сейчас не проводите модульное тестирование, я рекомендую начать с него. Получите хорошую книгу, подойдет практически любая xUnit-book, потому что понятия очень легко переносятся между ними.

Иногда написание юнит-тестов может быть болезненным. Когда это произойдет, попробуйте найти кого-то, кто поможет вам, и не поддавайтесь искушению «просто написать этот чертов код». Модульное тестирование очень похоже на мытье посуды. Это не всегда приятно, но поддерживает вашу метафорическую кухню в чистоте, и вы действительно хотите, чтобы она была чистой. :)


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

69 голосов
/ 04 августа 2008

Я не согласен с Дэном (хотя лучшим выбором может быть просто не отвечать) ... но ...

Модульное тестирование - это процесс написания кода для проверки поведения и функциональности вашей системы.

Очевидно, что тесты улучшают качество вашего кода, но это лишь поверхностное преимущество модульного тестирования. Реальные преимущества:

  1. Упростите изменение технической реализации, не изменяя поведения (рефакторинг). Код, протестированный надлежащим образом, может быть подвергнут агрессивному рефакторингу / очистке с небольшим шансом что-либо сломать, не замечая этого.
  2. Дайте разработчикам уверенность при добавлении поведения или внесении исправлений.
  3. Документируйте свой код
  4. Укажите области вашего кода, которые тесно связаны. Сложно связать код, который тесно связан
  5. Предоставьте средства для использования вашего API и найдите трудности на ранних этапах
  6. Обозначает методы и классы, которые не являются очень связными

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

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

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

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

44 голосов
/ 14 марта 2010

Основное отличие модульного тестирования от «простого открытия нового проекта и проверки этого конкретного кода» состоит в том, что он автоматизирован , то есть повторяется .

Если вы тестируете свой код вручную, он может убедить вас в том, что код работает отлично - в его текущем состоянии . Но как насчет недели спустя, когда вы внесли в нее небольшие изменения? Готовы ли вы повторно протестировать его вручную, когда что-нибудь изменится в вашем коде? Скорее всего, нет: - (

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

Это главное преимущество модульных тестов перед ручным тестированием. Но подождите, это еще не все:

  • модульные тесты значительно сокращают цикл обратной связи разработки : с отдельным отделом тестирования вам может потребоваться недели, чтобы узнать, что в вашем коде есть ошибка, к которой вы уже забыли большую часть контекст, таким образом, это может занять несколько часов, чтобы найти и исправить ошибку; OTOH с юнит-тестами, цикл обратной связи измеряется в секундах, и процесс исправления ошибки обычно происходит по принципу «ооооо, я забыл проверить это условие здесь»: -)
  • модульные тесты документ (ваше понимание) поведения вашего кода
  • модульное тестирование вынуждает вас пересмотреть свой выбор дизайна, что приводит к более простому, более чистому дизайну

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

33 голосов
/ 19 сентября 2008

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

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

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

Решение - модульные тесты. Они поймают проблемы, когда вы напишите код - и это нормально - но вы могли бы сделать это вручную. Реальная выгода в том, что они поймают проблемы через девять месяцев, когда вы сейчас работаете над совершенно другим проектом, но летний стажер думает, что это будет выглядеть более аккуратно, если бы эти параметры были в алфавитном порядке - и затем модульный тест Вы написали, что обратный путь не удался, и кто-то бросает вещи в стажера, пока он не изменит порядок параметров обратно. Это «почему» модульных тестов. : -)

13 голосов
/ 25 августа 2008

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

  1. TDD НЕ означает записи в два раза больше кода. Тестовый код, как правило, написан довольно быстро и безболезненно и является ключевой частью вашего процесса проектирования.

  2. TDD поможет вам понять, когда прекратить кодирование! Ваши тесты дают вам уверенность в том, что вы уже сделали достаточно и можете прекратить подстройку и перейти к следующему шагу.

  3. Тесты и код работают вместе для достижения лучшего кода. Ваш код может быть плохим / глючным. Ваш ТЕСТ может быть плохим / глючным. В TDD вы делаете ставку на то, что ОБА будет плохой / глючной, будучи довольно низкой. Часто это тест, который требует исправления, но это все же хороший результат.

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

  5. В том же духе, эти типы дизайнеров могут ВИДЕТЬ, над чем они работают. Они могут отправиться на перерыв на сок / сигарету / iphone и вернуться к монитору, который сразу же дает им визуальный сигнал о том, куда они попали. TDD дает нам нечто подобное. Проще понять, куда мы попали, когда вмешивается жизнь ...

  6. Я думаю, что это был Фаулер, который сказал: «Несовершенные тесты, выполняемые часто, намного лучше, чем совершенные тесты, которые вообще никогда не пишутся». Я интерпретирую это как предоставление мне разрешения на написание тестов, где я думаю, что они будут наиболее полезны, даже если остальная часть моего кода покрыта ужасно неполным.

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

Эта презентация является отличным введением во все вкусные испытания хорошего качества.

7 голосов
/ 14 марта 2010

Я бы хотел порекомендовать книгу Джерарда Месароса «Образцы тестирования xUnit». Это большой, но отличный ресурс по модульному тестированию. Вот ссылка на его веб-сайт, где он обсуждает основы модульного тестирования. http://xunitpatterns.com/XUnitBasics.html

5 голосов
/ 17 сентября 2008

Я использую модульные тесты, чтобы сэкономить время.

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

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

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

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

Для тестирования доступа к данным я стараюсь писать тесты, которые либо не меняются, либо очищаются после себя.

Юнит-тесты не смогут решить все требования к тестированию. Они смогут сэкономить время на разработку и протестировать основные части приложения.

4 голосов
/ 14 марта 2010

Библиотеки, такие как NUnit , xUnit или JUnit , просто обязательны, если вы хотите разрабатывать свои проекты с использованием подхода TDD , популяризируемого Кент Бек:

Вы можете прочитать Введение в разработку через тестирование (TDD) или книгу Кента Бека Разработка через тестирование: по примеру .

Затем, если вы хотите убедиться, что ваши тесты охватывают «хорошую» часть вашего кода, вы можете использовать программное обеспечение, такое как NCover , JCover , PartCover или что угодно. Они скажут вам процент покрытия вашего кода. В зависимости от того, насколько вы искусны в TDD, вы будете знать, достаточно ли хорошо вы это практиковали:)

4 голосов
/ 05 августа 2008

Это мое мнение. Я бы сказал, что модульное тестирование - это практика написания программных тестов, чтобы убедиться, что ваше реальное программное обеспечение выполняет то, для чего оно предназначено. Это началось с jUnit в мире Java и стало лучшей практикой в ​​PHP, а также с SimpleTest и phpUnit . Это основная практика экстремального программирования, которая помогает вам быть уверенным в том, что после редактирования ваше программное обеспечение по-прежнему работает так, как задумано. Если у вас есть достаточный охват тестированием, вы можете провести серьезный рефакторинг, исправить ошибку или быстро добавить функции с гораздо меньшим страхом появления других проблем.

Наиболее эффективно, когда все модульные тесты могут выполняться автоматически.

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

Фреймворк будет запускать все тесты для вашего кода, а затем сообщать об успехах или неудачах каждого теста. phpUnit по умолчанию запускается из командной строки Linux, хотя для него доступны HTTP-интерфейсы. SimpleTest является веб-интерфейсом по своей природе, и его гораздо проще запустить и запустить, IMO. В сочетании с xDebug phpUnit может предоставить вам автоматическую статистику для покрытия кода, что некоторые люди считают очень полезным.

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

Рекомендуется хранить свои модульные тесты в том же хранилище, что и ваше приложение.

3 голосов
/ 14 марта 2010

Я думаю, что вы не понимаете, что платформы модульного тестирования, такие как NUnit (и тому подобное), помогут вам автоматизировать тесты малого и среднего размера. Обычно вы можете запускать тесты в графическом интерфейсе (например, в случае NUnit ), просто нажав кнопку, а затем, будем надеяться, индикатор выполнения будет оставаться зеленым. Если он становится красным, рамки показывают, какой тест не пройден и что именно пошло не так. В обычном модульном тесте вы часто используете утверждения, например, Assert.AreEqual(expectedValue, actualValue, "some description") - поэтому, если два значения неравны, вы увидите сообщение об ошибке «некоторое описание: ожидалось , но было ».

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

...