Тестирование интеграции с Maven

Интеграционное тестирование с Maven

1. обзор

Maven - самый популярный инструмент сборки в пространстве Java, а интеграционное тестирование - неотъемлемая часть процесса разработки. Следовательно,it’s a natural choice to configure and execute integration tests with Maven.

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

2. подготовка

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

2.1. Конфигурация Maven

Мы создадим наше приложение REST на основе Джерси - эталонной реализации JAX-RS. Эта реализация требует пару зависимостей:


    org.glassfish.jersey.containers
    jersey-container-servlet-core
    2.27


    org.glassfish.jersey.inject
    jersey-hk2
    2.27

Мы можем найти последние версии этих зависимостейhere иhere.

Мы будем использовать плагин Jetty Maven для настройки тестовой среды. This plugin starts a Jetty server during the pre-integration-test phase of the Maven build lifecycle, then stops it in the post-integration-test phase.с

Вот как мы настраиваем плагин Jetty Maven вpom.xml:


    org.eclipse.jetty
    jetty-maven-plugin
    9.4.11.v20180605
    
        
            8999
        
        quit
        9000
    
    
        
            start-jetty
            pre-integration-test
            
                start
            
        
        
            stop-jetty
            post-integration-test
            
                stop
            
        
    

Когда сервер Jetty запускается, он будет прослушивать порт8999. Элементы конфигурацииstopKey иstopPort используются исключительно для цели плагинаstop, и их значение с нашей точки зрения не имеет значения.

Here - это место, где можно найти последнюю версию плагина Jetty Maven.

Также следует отметить, что мы должны установить для элементаpackaging в файлеpom.xml значениеwar, иначе плагин Jetty не сможет запустить сервер:

war

2.2. Создание приложения REST

Конечная точка приложения очень проста - возвращает приветственное сообщение, когда запрос GET попадает в корневой контекст:

@Path("/")
public class RestEndpoint {
    @GET
    public String hello() {
        return "Welcome to example!";
    }
}

Вот как мы регистрируем класс конечной точки в Джерси:

package com.example.maven.it;

import org.glassfish.jersey.server.ResourceConfig;

public class EndpointConfig extends ResourceConfig {
    public EndpointConfig() {
        register(RestEndpoint.class);
    }
}

Чтобы сервер Jetty знал о нашем приложении REST, мы можем использовать классический дескриптор развертыванияweb.xml:


    
        rest-servlet
        org.glassfish.jersey.servlet.ServletContainer
        
            javax.ws.rs.Application
            com.example.maven.it.EndpointConfig
        
    
    
        rest-servlet
        /*
    

This descriptor must be placed in the directory /src/main/webapp/WEB-INF для распознавания сервером.

2.3. Клиентский тестовый код

Все тестовые классы в следующих разделах содержат один метод:

@Test
public void whenSendingGet_thenMessageIsReturned() throws IOException {
    String url = "http://localhost:8999";
    URLConnection connection = new URL(url).openConnection();
    try (InputStream response = connection.getInputStream();
      Scanner scanner = new Scanner(response)) {
        String responseBody = scanner.nextLine();
        assertEquals("Welcome to example!", responseBody);
    }
}

Как мы видим, этот метод не делает ничего, кроме отправки запроса GET в веб-приложение, которое мы создали ранее, и проверки ответа.

3. Интеграционное тестирование в действии

При интеграционном тестировании важно отметить, чтоtest methods often take quite a long time to run.

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

A convenient way to separate integration tests is to use build profiles. Такая конфигурация позволяет нам выполнять интеграционные тесты только при необходимости - путем указания подходящего профиля.

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

4. Тестирование с помощью плагина Failsafe

Самый простой способ запустить интеграционные тесты - использоватьthe Maven failsafe plugin.

По умолчанию плагин Mavensurefire выполняет модульные тесты на этапеtest, аthe failsafe plugin runs integration tests in the integration-test phase.

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

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

Выполнение плагинаsurefire включает все классы, имя которых начинается сTest или заканчивается наTest,Tests илиTestCase. Напротив, плагинfailsafe выполняет тестовые методы в классах, имя которых начинается сIT или заканчивается наIT илиITCase.

This - это то место, где мы можем найти документацию относительно включения тестов дляsurefire, аhere - дляfailsafe.

Давайте добавим плагинfailsafe в POM с конфигурацией по умолчанию:


    failsafe
    
        
            
                maven-failsafe-plugin
                2.22.0
                
                    
                        
                            integration-test
                            verify
                        
                    
                
            
        
    

This link - это место, где найти последнюю версию плагинаfailsafe.

В приведенной выше конфигурации на этапеintegration-test будет выполняться следующий метод тестирования:

public class RestIT {
    // test method shown in subsection 2.3
}

Поскольку сервер Jetty запускается на этапеpre-integration-test и выключается черезpost-integration-test, тест, который мы только что видели, проходит с помощью этой команды:

mvn verify -Pfailsafe

Мы также можем настроить шаблоны именования для включения классов с разными именами:


    maven-failsafe-plugin
    2.22.0
    
        
            **/*RestIT
            **/RestITCase
        
    
    ...

5. Тестирование с помощью плагина Surefire

Помимо плагинаfailsafe,we can also use the surefire plugin to execute unit and integration tests in different phases.

Предположим, мы хотим назвать все интеграционные тесты суффиксомIntegrationTest. Поскольку плагинsurefire по умолчанию запускает тесты с таким именем в фазеtest, нам нужно исключить их из выполнения по умолчанию:


    maven-surefire-plugin
    2.22.0
    
        
            **/*IntegrationTest
        
    

Последняя версия этого плагинаhere.

Мы исключили все тестовые классы, имена которых заканчиваются наIntegrationTest, из жизненного цикла сборки. Пора вернуть их в профиль:


    surefire
    
        
            
                maven-surefire-plugin
                2.22.0
                
                    
                        integration-test
                        
                            test
                        
                        
                            
                                none
                            
                            
                                **/*IntegrationTest
                            
                        
                    
                
            
        
    

Instead of binding the test goal of the surefire plugin to the test build phase, as usual, we bound it to the integration-test phase. Затем плагин запустится во время процесса тестирования интеграции.

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

Теперь давайте определим тестовый класс интеграции с нашим шаблоном именования:

public class RestIntegrationTest {
    // test method shown in subsection 2.3
}

Этот тест будет выполняться с помощью команды:

mvn verify -Psurefire

6. Тестирование с помощью плагина Cargo

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

Более подробную информацию об этой комбинации можно найти вhere.

7. Тестирование с помощью JUnit's@Category

Удобный способ выборочного выполнения тестов - использоватьthe @Category annotation в среде JUnit 4. This annotation lets us exclude particular tests from unit testing, and include them in integration testing.

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

package com.example.maven.it;

public interface Integration { }

Затем мы можем украсить тестовый класс аннотацией@Category и идентификаторомIntegration:

@Category(Integration.class)
public class RestJUnitTest {
    // test method shown in subsection 2.3
}

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

Исключить категорию из фазы сборкиtest просто:


    maven-surefire-plugin
    2.22.0
    
        com.example.maven.it.Integration
    

Включение категорииIntegration в фазуintegration-test также несложно:


    category
        
        
            
                maven-failsafe-plugin
                2.22.0
                
                    
                        **/*
                    
                    com.example.maven.it.Integration
                
                
                    
                        
                            integration-test
                            verify
                        
                    
                
            
        
    

Теперь мы можем запустить интеграционные тесты с помощью команды Maven:

mvn verify -Pcategory

8. Добавление отдельного каталога для интеграционных тестов

Иногда желательно иметь отдельный каталог для интеграционных тестов. Organizing tests this way allows us to entirely isolate integration tests from unit tests.с

Для этого мы можем использовать плагин Mavenbuild helper:


    org.codehaus.mojo
    build-helper-maven-plugin
    3.0.0
    
        
            add-integration-test-source
            generate-test-sources
            
                add-test-source
            
            
                
                    src/integration-test/java
                
            
        
    

Here - это место, где мы можем найти последнюю версию этого плагина.

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

public class RestITCase {
    // test method shown in subsection 2.3
}

Пришло время запустить интеграционные тесты в этом классе:

mvn verify -Pfailsafe

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

Каталог с тестовым исходным кодом часто идет вместе с каталогом ресурсов. Мы можем добавить такой каталог в другой элементexecution в конфигурацию плагина:


    ...
    
        add-integration-test-resource
        generate-test-resources
        
            add-test-resource
        
        
            
                
                    src/integration-test/resources
                
            
        
    

9. Заключение

В этой статье мы рассмотрели использование Maven для запуска интеграционных тестов с сервером Jetty, уделяя особое внимание настройке плагинов Mavensurefire иfailsafe.

Полный исходный код этого руководства можно найти наover on GitHub.