Почему юнит-тесты должны выполняться отдельно от интеграционных тестов
TDD на уровне модульного тестирования довольно прост, так как классы в модульном тестировании либо не имеют сложных зависимостей, либо вы макетируете эти зависимости с помощью среды моделирования (например, Mockito). Тем не менее, TDD быстро становится трудным, когда мы начинаем интеграционное тестирование . Интеграционное тестирование — это, в основном, тестирование компонента с некоторыми или всеми его зависимостями вместо того, чтобы проверять их все. Примерами являются тесты, проходящие через несколько уровней, тесты, которые читают или записывают в базу данных или файловую систему, тесты, которые требуют наличия контейнера сервлета или EJB-контейнера, тесты, которые включают сетевое взаимодействие, веб-службы и т. Д.
Интеграционные тесты обычно бывают хрупкими и / или медленными . Примеры:
- Тест, который обращается к БД, может потерпеть неудачу не потому, что логика в коде была неправильной, а потому, что БД не работает, URL / имя пользователя / пароль к БД были изменены, или в БД были неправильные данные.
- Тесты, которые читают или записывают на диск, медленные, и каждый раз, когда вы запускаете тест, файл или база данных должны быть сброшены с правильными данными или содержимым.
- Упаковка и развертывание в контейнере происходит медленно.
- Тесты, выполняющие сетевые вызовы, могут завершиться неудачей не потому, что логика в коде неверна, а потому, что сетевой ресурс недоступен или существуют проблемы с самой сетью.
Эти трудности, как правило, мешают разработчикам часто запускать тесты. Когда тесты выполняются мало и далеко, разработчики заканчивают тем, что пишут много кода прежде, чем они поймают ошибки. Поэтому, когда тесты запускаются нечасто, производительность снижается, потому что ошибки труднее находить и исправлять после написания большого количества кода, и существует повышенный риск проблем с качеством. Кроме того, когда выполнение тестов является проблемой, разработчики не должны писать достаточно тестов.
Поэтому имеет смысл запускать модульные тесты отдельно от интеграционных тестов. Модульные тесты выполняются полностью в памяти без каких-либо внешних зависимостей, поэтому даже для больших проектов все они должны выполняться всего за несколько секунд и каждый раз должны работать надежно, поскольку они зависят только от логики тестируемого кода. Поэтому разработчикам рекомендуется запускать все свои модульные тесты с каждым небольшим изменением.
Использование Maven Failsafe и JUnit @Category для разделения интеграционных тестов
Существует несколько способов разделения интеграционных тестов. По умолчанию Failsafe выбирает любой класс с суффиксом «IT» или «ITCase» или с префиксом «IT». Однако для некоторых сред тестирования также требуются суффиксы или префиксы, что делает использование этого подхода громоздким. Другой подход заключается в размещении интеграционных тестов в отдельном исходном каталоге. Я решил использовать JUnit @Category, так как я также использую Concordion, который требует суффикса в своих тестовых классах.
В оставшейся части этой статьи только документируется, как я реализовал совет из статьи Джона Доубла 2012 года, озаглавленной «Юнит-тесты и интеграционные тесты с категориями Maven и JUnit» . Вы можете найти мой исходный код здесь .
Создание категории JUnit
Создание категории JUnit — это просто создание пустого интерфейса. На самом деле, это все! См. ниже:
1
2
3
4
5
|
package com.orangeandbronze.test; public interface IntegrationTest { } |
Теперь я могу применить этот «маркерный интерфейс» в качестве категории к моим интеграционным тестам — в приведенном ниже примере к SectionDaoTest.
1
2
3
4
5
6
7
|
import org.junit.experimental.categories.Category; import com.orangeandbronze.test.IntegrationTest; @Category (IntegrationTest. class ) public class SectionDaoTest extends DaoTest { ... } |
Добавление плагинов Surefire и Failsafe
Теперь добавьте плагины Surefire и Failsafe. Мне нужно исключить все тесты, отмеченные IntegrationTest в Surefire (который запускает модульные тесты), и включить все тесты, отмеченные IntegrationTest в Failsafe (который запускает интеграционные тесты). Кроме того, я должен был включить «** / *. Java» или тесты не запускаются, я не знаю почему.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
< plugin > < artifactId >maven-surefire-plugin</ artifactId > < version >2.18.1</ version > < configuration > < excludedGroups >com.orangeandbronze.test.IntegrationTest</ excludedGroups > </ configuration > </ plugin > < plugin > < artifactId >maven-failsafe-plugin</ artifactId > < version >2.18.1</ version > < configuration > < includes > < include >**/*.java</ include > </ includes > < groups >com.orangeandbronze.test.IntegrationTest</ groups > </ configuration > < executions > < execution > < goals > < goal >integration-test</ goal > < goal >verify</ goal > </ goals > </ execution > </ executions > </ plugin > |
Выполнение тестов
Итак, теперь, когда я запускаю mvn test, запускаются только модульные тесты, тогда как когда я запускаю mvn интеграционный тест или mvn verify (я обычно запускаю mvn verify), не только выполняется модульный тест, но и мой проект упаковывается, а затем запуск интеграционных тестов
В реальном проекте каждый разработчик запускает все модульные тесты после нескольких изменений, десятки раз в день, в то время как интеграционные тесты он запускает реже, но не реже одного раза в день. Сервер CI также будет выполнять модульные и интеграционные тесты во время сборки.
Ссылка: | Отделение интеграционных тестов от юнит-тестов с использованием Maven Failsafe & JUnit @Category от нашего партнера по JCG Калена Легаспи в блоге |