Вопрос

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

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

Решение

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

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

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

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

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

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

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


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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

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

Платформы модульного тестирования, в свою очередь, упрощают написание и запуск тестов.

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

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

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

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

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

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

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

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

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

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

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

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

Эта презентация - отличное введение во все, что влечет за собой тестирование вкусностей.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Библиотеки как НУнит, xUnit или Юнит просто обязательны, если вы хотите разрабатывать свои проекты с использованием ТДД подход, популяризированный Кентом Беком:

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

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

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

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

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

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

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

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

А Единица часть названия говорит о намерении тестировать небольшие блоки кода (например, один метод) за раз.

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

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

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

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

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

Использовать Тестивус.Все, что вам нужно знать, здесь :)

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

xUnit, НУнит, мбЮнит, и т. д.— это инструменты, которые помогут вам в написании тестов.

Разработка через тестирование в некотором роде взяла на себя термин «модульное тестирование».Как старожил, я упомяну более общее определение этого понятия.

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

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

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

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

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

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

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

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

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

На данный момент мы превысили 40%, и нам удалось сорвать большую часть легко висящих плодов.

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

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


В трех видеороликах ниже рассказывается о модульном тестировании на 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).Допустим, вы модифицируете функцию, которая используется каким-то скриптом на веб-странице, и она отлично работает для своего нового предназначения.Но давайте также в качестве аргумента скажем, что где-то еще в вашем коде есть еще одна функция, правильная работа которой зависит от этой недавно измененной функции.Эта зависимая функция теперь может перестать работать из-за изменений, которые вы внесли в первую функцию, однако без тестов, которые автоматически запускаются вашим компьютером, вы не заметите, что существует проблема с этой функцией, пока она не будет фактически выполнена и вам придется вручную перейти на веб-страницу, содержащую сценарий, выполняющий зависимую функцию, только тогда вы заметите, что возникла ошибка из-за изменения, внесенного вами в первую функцию.

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


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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top