Зачем использовать JUnit для тестирования?

131

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

Пишу ли я простые приложения или более крупные, я тестирую их с помощью System.outоператоров, и мне это кажется довольно простым.

Зачем создавать тестовые классы с JUnit, ненужные папки в проекте, если нам по-прежнему нужно вызывать те же методы, проверять, что они возвращают, и тогда у нас есть накладные расходы на аннотирование всего?

Почему бы не написать класс и не протестировать его сразу, System.outно не создать Test-классы?

PS. Я никогда не работал над большими проектами, я только учусь.

Так в чем же цель?

Артем Москалев
источник
1
Прочтите Искусство
модульного
7
Вы знаете, что каждый раз, когда вы изменяете что-либо в своей программе, вся ваша предыдущая работа по проверке результатов вручную становится недействительной, и вам придется переделывать их с самого начала?
Thorbjørn Ravn Andersen
Не только «тестирование», но и «умное тестирование» очень важно. Вот хороший пример: wp.me/prMeE-11
akcasoy

Ответы:

139

Это не тестирование, это «просмотр результатов вручную» (известный в бизнесе как LMAO). Более формально это известно как «ручной поиск аномального вывода» (LMFAO). (См. Примечание ниже)

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

Теперь масштабируйте до 50k, 250k, 1m LOC или более и LMFAO при каждом изменении кода. Это не только неприятно, но и невозможно: вы увеличили масштабы комбинаций входов, выходов, флагов, условий, и вам трудно использовать все возможные ветви.

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

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

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


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

Дэйв Ньютон
источник
3
-1 за первое предложение, которое полностью и совершенно не соответствует действительности.
Майкл Боргвардт
50

Мы пишем тесты для проверки корректности поведения программы.

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

Вы можете утверждать, что

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Роб Келти
источник
13

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

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

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

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

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

jmort253
источник
9

Я добавил еще кое-что, чего не может сделать System.out:

  • Сделайте каждый тестовый набор независимым (это важно)

    JUnit может это сделать: каждый раз создается и @Beforeвызывается новый экземпляр тестового примера .

  • Отдельный тестовый код от исходного кода

    JUnit может это сделать.

  • Интеграция с CI

    JUnit может сделать это с помощью Ant и Maven.

  • Легко упорядочивайте и комбинируйте тестовые примеры

    JUnit может делать @Ignoreи тестировать набор.

  • Легко проверить результат

    JUnit предлагает множество методов Assert ( assertEquals, assertSame...)

  • Мок и заглушка заставляют сосредоточиться на тестовом модуле.

    JUnit может: Использование макета и заглушки позволяет настроить правильное устройство и сосредоточиться на логике тестового модуля.

卢 声 远 Шэнъюань Лу
источник
9

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

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

в JUnit есть также некоторые более продвинутые функции, например

Утверждать заявления

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

Некоторые из этих методов

  1. fail([message])- Пусть тест не пройден. Может использоваться для проверки того, что определенная часть кода не достигнута. Или иметь неудачный тест до того, как будет реализован тестовый код.
  2. assertTrue(true)/ assertTrue(false)- Всегда будет истинным / ложным. Может использоваться для предварительного определения результата теста, если тест еще не реализован.
  3. assertTrue([message,] condition)- Проверяет, что логическое значение conditionистинно.
  4. assertEquals([message,] expected, actual)- Проверяет, равны ли два значения (в соответствии с equalsметодом, если он реализован, в противном случае с использованием ==сравнения ссылок). Примечание. Для массивов проверяется ссылка, а не содержимое, используемое assertArrayEquals([message,] expected, actual)для этого.
  5. assertEquals([message,] expected, actual, delta)- Проверяет, находятся ли два значения типа float или double на определенном расстоянии друг от друга, контролируемом deltaзначением.
  6. assertNull([message,] object) - Проверяет, что объект нулевой

и так далее. См. Полную Javadoc для всех примеров здесь .

Suites

С помощью наборов тестов вы можете в некотором смысле объединить несколько тестовых классов в один модуль, чтобы выполнять их все одновременно. Простой пример, сочетающее в себе тестовые классы MyClassTestи MySecondClassTestв один люкс под названием AllTests:

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({ MyClassTest.class, MySecondClassTest.class })
public class AllTests { } 
Эрвинд
источник
6

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

n00begon
источник
4

JUnit - это среда модульного тестирования для языка программирования Java. Он важен для разработки, управляемой тестированием, и является одним из семейства фреймворков модульного тестирования, известных под общим названием xUnit.

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

Особенности JUnit - это среда с открытым исходным кодом, которая используется для написания и выполнения тестов.

Предоставляет аннотацию для определения методов тестирования.

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

Предоставляет средства запуска тестов для запуска тестов.

Тесты JUnit позволяют писать код быстрее, что повышает качество

JUnit элегантно прост. Это менее сложно и занимает меньше времени.

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

Тесты JUnit могут быть организованы в наборы тестов, содержащие тестовые примеры и даже другие наборы тестов.

Junit показывает прогресс теста в зеленой полосе, если тест проходит успешно, и становится красной, если тест не пройден.

Äkki
источник
2

У меня несколько иное мнение о том, зачем нужен JUnit.

На самом деле вы можете написать все тестовые примеры самостоятельно, но это громоздко. Вот проблемы:

  1. Вместо этого System.outмы можем добавить if(value1.equals(value2))и вернуть 0 или -1 или сообщение об ошибке. В этом случае нам нужен «основной» тестовый класс, который запускает все эти методы, проверяет результаты и поддерживает, какие тестовые примеры не прошли, а какие пройдены.

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

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

Вот что делает JUnit:

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

  2. «основной» класс называется runner, который предоставляется JUnit, поэтому нам не нужно ничего писать. И он автоматически определяет методы тестирования путем отражения. Если вы добавляете новые тесты с @Testаннотациями, они обнаруживаются автоматически.

  3. JUnit имеет интеграцию с eclipse и maven / gradle, поэтому запускать тесты легко, и вам не придется писать собственные конфигурации запуска.

Я не эксперт в JUnit, поэтому сейчас я понял, что в будущем добавлю больше.

Sreekar
источник
Думаю, в первой части вы написали, что мы сделали бы, если бы там не было JUnit, чтобы модульное тестирование было немного лучше, чем операторы system.out.println. Возможно, JUnit является результатом таких попыток некоторых программистов, и они почувствовали необходимость написать отдельную среду тестирования для выполнения этой автоматизации, возможно, так и родился JUnit.
Саураб Патил,
1

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

Что такое Юнит?

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

Важные особенности тестирования Junit -

  1. Это среда тестирования с открытым исходным кодом, позволяющая пользователям эффективно писать и запускать тестовые примеры.
  2. Предоставляет различные типы аннотаций для определения методов тестирования.
  3. Предоставляет различные типы утверждений для проверки результатов выполнения тестового примера.
  4. Он также дает средства запуска тестов для эффективного выполнения тестов.
  5. Это очень просто и, следовательно, экономит время.
  6. Он предоставляет способы организовать ваши тестовые примеры в виде тестовых костюмов.
  7. Он дает результаты теста простым и элегантным способом.
  8. Вы можете интегрировать jUnit с Eclipse, Android Studio, Maven & Ant, Gradle и Jenkins.
ануджа джайн
источник
0

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

мохит сарсар
источник
0

ИЮНЬ: СОБЛЮДАЙТЕ И ОТРЕГУЛИРУЙТЕ

Вот мой взгляд на JUNIT.

JUNIT можно использовать для:
1) наблюдения за поведением системы при добавлении нового модуля в эту систему.
2) Сделайте настройку в системе, чтобы приветствовать «новый» блок в системе.
Какой? Именно.

Реальная жизнь, например.

Когда ваш родственник посещает вашу комнату в общежитии колледжа,
1) вы будете притворяться более ответственным.
2) Вы будете хранить все вещи там, где они должны быть, например, обувь в стойке для обуви, а не на стуле, одежду в шкафу, а не на стуле.
3) Вы избавитесь от всей контрабанды.
4) вы начнете чистку на каждом устройстве, которое у вас есть.

С точки зрения программирования

Система: Ваш код
UNIT: новый функционал.
Поскольку среда JUNIT используется для языка JAVA, JUNIT = JAVA UNIT (может быть).

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

Простой способ адаптировать это изменение - использовать модульное тестирование (JUNIT).
Для этого вы должны написать несколько тестовых сценариев для своего кода при создании своей кодовой базы. И всякий раз, когда появляется новое требование, вы просто запускаете все тестовые примеры, чтобы увидеть, не завершился ли какой-либо тестовый пример. Если нет, значит, вы являетесь исполнителем BadA ** и готовы к развертыванию нового кода.
Если какой-либо из тестовых наборов терпит неудачу, вы меняете свой код и снова запускаете тестовые наборы, пока не получите зеленый статус.

Рохит Сингх
источник