JUnit vs TestNG: вскрытие рамок тестирования
Тестирование является неотъемлемой частью цикла выпуска программного обеспечения в хорошо сбалансированных командах разработчиков. И так было не всегда. Модульные тесты, интеграционные тесты, системные тесты и другие не всегда были рядом. Сегодня нам повезло, что мы попали в то время, когда тестирование имеет значение, и ценность известна большинству заинтересованных сторон.
В этой статье мы поместим тестирование в центр и рассмотрим тестирование Java глазами JUnit и TestNG, сравнивая их основные функции и варианты использования.
Огромное спасибо Сассону Шмуэлю, инженеру по автоматизации испытаний OverOps, за помощь в написании поста.
Итак … Что бы вы выбрали, учитывая чистую доску?
1. Познакомьтесь с рамками
JUnit и TestNG, без сомнения, являются самыми популярными средами тестирования. Фактически, когда мы изучали библиотеки, которые используют лучшие проекты Java в GitHub, оба они вошли в двадцатку лучших .
JUnit занял первое место с присутствием в 62% проектов, а TestNG был на # 20 с 6%. Репозиторий Maven показывает аналогичные результаты: JUnit взлетел на диаграммах популярности в № 1 с 42 484 использованиями, а TestNG — в № 15 с 3873 использованиями. Это также потому, что JUnit добавляется по умолчанию во многих архетипах Maven.
Версии и немного недавней истории
Последняя версия JUnit — 4.12, выпущенная в декабре 2014 года. Ожидается, что JUnit 5 достигнет статуса GA в конце 2016 года. Это очень скоро, и мы также ожидаем, что это станет горячей темой на конференциях.
JUnit был одним из драйверов для разработки Test Driven Development, изначально разработанной Кентом Беком и Эрихом Гаммой . В 2013 году факел был передан команде JUnit :
Ранняя версия JUnit 5 уже доступна для вас, и вы также можете внести свой вклад в ее разработку на GitHub . Интересен тот факт, что разработка новой версии стала возможной благодаря краудфандинговой кампании .
Что касается TestNG, который был создан Седриком Беустом , последняя версия на момент написания этой статьи — 6.9.10 с декабря 2015 года. Она впервые появилась примерно в то время, когда JUnit 3 еще был, и предлагала новые функции, которых не было время с дизайном, ориентированным на более широкие варианты тестирования. Некоторые из этих функций, такие как использование аннотаций, были добавлены в JUnit 4, и это версия, на которой мы сосредоточены здесь, с перспективой на предстоящий выпуск JUnit 5.
2. Написание тестов
И TestNG, и JUnit основаны на поведении, аналогичном утверждениям Java, которые были добавлены еще в Java 4. И мы можем просто использовать утверждения напрямую, так что … зачем беспокоиться об инфраструктуре тестирования?
Легко поддаться искушению, начиная с простых утверждений Java, но по мере роста проекта тестирование быстро становится нетривиальным, и имеет смысл использовать инфраструктуру для управления им. Более того, кривая обучения довольно быстрая, а основные концепции просты, но мощны. Кодовая база JUnits настолько легка, что Мартина Фаулера лихо цитировали:
«Никогда в области разработки программного обеспечения столько людей не были так многим обязаны столь малому количеству строк кода»
И JUnit, и TestNG следуют соглашениям xUnit , но у них есть несколько отличий, которые мы хотели бы здесь подчеркнуть. Группы, параллелизм, параметризованный тест и зависимости:
группы
TestNG предлагает дополнительные аннотации к тем, которые доступны в JUnit. Вероятно, наиболее примечательной является способность запускать код до / после групп тестовых случаев. Кроме того, отдельные тесты могут принадлежать нескольким группам и затем выполняться в разных контекстах (например, медленные или быстрые тесты). Это практически еще один слой между тестовым набором и набором тестов:
1
|
@Test (groups = { "sanity" , "insanity" }) |
Аналогичная функция существует в категориях JUnit, но в ней отсутствуют аннотации @BeforeGroups / @AfterGroups TestNG, которые позволяют инициализировать тестирование или его демонтаж. Кстати, похоже, что JUnit 5 собирается отказаться от Категорий и ввести новую концепцию, которая будет называться Tag:
1
2
3
4
5
|
@Tag ( "sanity" ) @Tag ( "insanity" ) void testSomething() { ... } |
Но, как это выглядит сейчас, аннотаций @BeforeTag / @AfterTag не видно.
параллелизм
Если вы хотите запустить один и тот же тест параллельно в нескольких потоках, TestNG предоставит вам простую в использовании аннотацию, в то время как JUnit не предлагает простой способ сделать это из коробки. Реализация TestNG будет выглядеть так:
1
2
3
4
|
@Test (threadPoolSize = 3 , invocationCount = 9 ) public void testSomething() { ... } |
Значение 3 потока и 9 вызовов одного и того же теста. Вы также можете запускать целые комплекты параллельно, если указали это в конфигурациях прогона TestNG XML. В то время как с JUnit вам придется написать собственный метод бегуна и подавать одни и те же параметры тестирования несколько раз. Что подводит нас к следующему пункту пули.
Параметризованное / управляемое данными тестирование
Это проблема подачи разных тестовых входных данных в один и тот же тестовый пример, который решают и TestNG, и JUnit, но используют разные подходы. Основная идея та же: создание двумерного массива Object [] [], который включает параметры.
Однако в дополнение к предоставлению параметров через код TestNG @DataProvider также может поддерживать XML для подачи данных, CSV-файлов или даже текстовых файлов.
Функция, которая существует в JUnit и отсутствует в TestNG, — это возможность использовать различные комбинации между несколькими аргументами. Это обеспечивает быстрый доступ к длинному списку параметров и объясняется в JUnit Theories .
Зависимости между группами / методами
Поскольку JUnit был создан для модульных тестов, а TestNG имел в виду более широкий спектр тестов, они также отличаются подходом к зависимостям между тестами.
TestNG позволяет объявлять зависимости между тестами и пропускать их, если тест на зависимости не прошел:
1
2
3
4
|
@Test (dependsOnMethods = { "dependOnSomething" }) public void testSomething() { ... } |
Эта функциональность не существует в JUnit, НО можно эмулировать, используя предположения . Неудачное предположение приводит к игнорированию теста, который пропускается.
Итог: разные разработчики будут иметь разные ожидания от их структуры выбора. TestNG обеспечивает большую гибкость из коробки по сравнению с JUnit.
3. Запуск тестов
При написании тестов нам не нужно включать метод main, поскольку фреймворки запускают эти тесты для нас со своим собственным методом main, который управляет выполнением отдельных тестов.
Если вам нужен пользовательский бегун, JUnit предоставляет аннотацию @RunWith, которая позволяет вам использовать свой собственный бегун. Обойти бегуна по умолчанию также возможно с TestNG, но не так просто, как с JUnit. Тем не менее, стоит отметить, что TestNG поддерживает конфигурации запуска XML, которые оказываются полезными во многих случаях использования.
Что касается фактического запуска тестов, то обе платформы имеют поддержку CLI, работающую через ANT, и плагины, доступные для выбранной вами IDE с довольно схожей функциональностью. Хотя JUnit выходит из коробки с JDT (Eclipse Java Development Tools), так оно и есть.
Итог: JUnit немного более гибок благодаря аннотации @RunWith.
4. Отчетность по результатам
Результаты теста интересуют многих людей. Это не только разработчик, который управляет ими. Это когда отчеты вступают в игру, и обе платформы имеют ответ на этот вопрос.
Отчеты TestNG по умолчанию создаются в папке с тестовым выходом, которая содержит html-отчеты со всеми тестовыми данными, прошедшими / неудачными / пропущенными, как долго они выполнялись, какой вход использовался и полные журналы тестов. Кроме того, он также экспортирует все в файл XML, который можно использовать для создания собственного шаблона отчета.
Что касается JUnit, все эти данные также доступны через XML, но нет готового отчета, и вам нужно полагаться на плагины.
Итог: TestNG предоставляет готовые отчеты, JUnit экспортирует их только в XML
5. Автоматизация тестовых прогонов
Обе платформы могут использоваться для создания автоматизированных тестовых прогонов с помощью таких инструментов, как Jenkins, Travis CI и Teamcity. Также доступны плагины для создания отчетов из тестовых данных и отправки их всем, кого интересует выбранный вами канал. Например, используя TestNG с Jenkins и интегрируя его с электронной почтой и Slack.
Мы также ранее писали о некоторых из самых полезных интеграций Slack для разработчиков, посмотрите это .
Итог: автоматизация для победы. И JUnit, и TestNG, вероятно, имеют нужные вам интеграции.
6. Убить проваленный тест
К сожалению, мы провалили тест. Что происходит дальше? Если он достаточно детализирован, найти причину неудачи будет относительно легко, но реальность часто имеет другие планы для нас.
Несмотря на то, что он в основном предназначен для производственных сред, у значительной части наших пользователей также настроены OverOps для мониторинга их среды тестирования. Всякий раз, когда тест не проходит, они могут просматривать переменные, которые вызвали ошибку, во всех методах, которые привели к этому.
Итог: чтобы вывести свою среду на следующий уровень, проверьте OverOps и посмотрите, как она может помочь вам в устранении ошибок.
7. Пересмешивание, сопоставление и другие рамки
Сообщение в блоге о тестировании Java, JUnit и TestNG не может быть полным без упоминания некоторых дополнительных библиотек тестирования.
В этом разделе мы кратко рассмотрим эти категории с помощью самых популярных библиотек в соответствии с ведущими проектами GitHub в Java .
осмеяние
Хорошей практикой является выполнение модульных тестов изолированно, но что, если тестируемый компонент зависит от других сложных объектов? Вот где появляется насмешка, и вы можете создавать имитирующие объекты, которые имитируют поведение, которое вам нужно из других частей системы:
согласование
Утверждения, предоставляемые JUnit и TestNG, довольно просты, использование сопоставителя повышает их читабельность и добавляет больше возможностей для выбора:
- Hamcrest (# 34, 4,12% проектов)
- AssertJ (№ 55, 2,72% проектов)
- Еще одна библиотека, которую стоит проверить, — Google Truth , о которой мы писали в качестве части поста об интересных Java-проектах от Google (помимо Guava) .
И… Спок
Spock — это готовый к запуску Groovy ( не тот, отличный от Groovy ) фреймворк для тестирования, основанный на JUnit. Идея заключается в том, чтобы объединить эту экосистему тестовых библиотек в единую инфраструктуру с помощью простого Groovy DSL. Мы рассмотрели некоторые из его функциональных возможностей в посте о Groovy и его использовании для Java . Для более глубокого сравнения посмотрите эти слайды от Kostis Kapelonis .
Итог: тестирование обычно не останавливается на одной платформе, познакомьтесь с другими библиотеками в игре.
8. Сообщество
JUnit имеет больше истории и значительно большую пользовательскую базу, он в основном определил стандарт для модульного тестирования Java. Таким образом, у него самая большая пользовательская база, и довольно легко найти ответ или кого-то, кто мог бы спросить о любой проблеме, которая может у вас возникнуть.
У TestNG может быть меньше пользователей, но его сообщество не отстает (хотя его веб-сайт может использовать фейслифтинг). И … оба могут извлечь выгоду из некоторых руководящих принципов логотипа. Есть дизайнеры в толпе?
Вот еще несколько полезных ссылок для JUnit:
- Сайт JUnit 4 и репозиторий GitHub
- Сайт JUnit 5 и репозиторий GitHub
И TestNG:
- Сайт TestNG и репозиторий GitHub
- Дискуссионная группа TestNG
Итог: вы не потеряетесь ни с одним из них.
Последние мысли
Тестирование Java прошло долгий путь, и мы рады, что тестирование имеет значение. Основным выводом здесь является создание значимого теста.
С этим сказал …
Какие рамки вы используете и почему? Что бы вы выбрали, учитывая чистый лист? Дайте нам знать в комментариях ниже.
Ссылка: | JUnit vs TestNG: какую среду тестирования выбрать? от нашего партнера JCG Алекса Житницкого в блоге OverOps . |