Что такое модульное тестирование?


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

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

20 ответов:

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Я хотел бы порекомендовать книгу xUnit Testing Patterns от Gerard Meszaros. Он большой, но является отличным ресурсом для модульного тестирования. Вот ссылка на его сайт, где он обсуждает основы модульного тестирования. http://xunitpatterns.com/XUnitBasics.html

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

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

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

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

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

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

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

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

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

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

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

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

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

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

вы можете узнать введение в разработку на основе тестирования (TDD) или книга Кента Бека

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

The Unit часть имени посвящена намерению тестировать небольшие единицы кода (например, один метод) за раз.

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

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

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

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

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

использовать Testivus. Все, что вам нужно знать, прямо там:)

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

xUnit,Нанит,mbUnit и т. д. несколько инструментов, которые помогут вам в написании тестов.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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

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