Что такое юнит-тестирование? [закрыто]


211

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

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

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

Чистый код говорит: youtube.com/watch?v=wEhu57pih5w
Киран

1
Это не 1 конкретный вопрос. Это 5 широких вопросов.
Raedwald

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

Ответы:


197

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

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

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

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

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

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

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


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


2
Не могли бы вы рассказать о том, как TDD ускоряет разработку?
Мартин

70

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

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

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

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

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

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

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

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


44

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

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

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

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

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

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


+1 Кроме того, моя любимая часть о тестовом коде (особенно при наличии новой кодовой базы): демонстрирует ожидаемое использование тестируемого кода.
Стивен Эверс

34

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

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

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

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


13

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

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

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

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

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

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

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

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

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


7

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


5

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

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

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

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

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

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

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


4

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

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

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

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

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

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


4

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

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

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


3

Модульное тестирование - это тестирование единицы кода (например, одной функции) без необходимости инфраструктуры, на которую опирается эта единица кода. т.е. проверить это в изоляции.

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

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

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

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


3

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

Часть « Unit» в названии предназначена для тестирования небольших блоков кода (например, одного метода) за раз.

xUnit помогает с этим тестированием - это фреймворки, которые помогают с этим. Частично это автоматизированные тестеры, которые сообщают вам, какой тест не пройден и какие пройдены.

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

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


3

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

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



3

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

xUnit , NUnit , mbUnit и т. д. - это инструменты, которые помогут вам в написании тестов.


2

Test Driven Development переняла термин «модульный тест». Как старый таймер я упомяну более общее определение этого.

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

Затем вы перейдете к интегрированному или системному тестированию, проверив, как все компоненты работают вместе.


2

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


1

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

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

Я не дошел до конца, потому что мне нужно было рутина, а теперь черт, но это было хорошее упражнение.


1

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

Как мы можем провести модульное тестирование?

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

Прямо сейчас у нас более 40%, и нам удалось собрать большинство низко висящих фруктов.

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


1

Это отвечает, почему вы должны проводить юнит-тестирование.


3 видео ниже описывают юнит-тестирование в javascript, но общие принципы применимы ко всем языкам.

Модульное тестирование: минуты теперь сэкономят часы спустя - Эрик Манн - https://www.youtube.com/watch?v=_UmmaPe8Bzc

Юнит-тестирование JS (очень хорошо) - https://www.youtube.com/watch?v=-IYqgx8JxlU

Написание тестируемого JavaScript - https://www.youtube.com/watch?v=OzjogCFO4Zo


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

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


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

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


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

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


0

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.