Статьи

Java EE, Gradle и интеграционные тесты

В последние годы Apache Maven стал инструментом де-факто для проектов Java и Java EE . Но с двухлетней давности Gradle набирает все больше и больше пользователей. После моего предыдущего поста ( http://www.lordofthejars.com/2015/10/gradle-and-java-ee.html ), в этом посте вы узнаете, как использовать Gradle для написания интеграционных тестов для Java EE с использованием Аркиллиан .

Gradle — это инструмент автоматизации сборки, такой как Ant или Maven, но представляющий основанный на Groovy язык DSL вместо XML. Так что, как и следовало ожидать, файл сборки является файлом Groovy. Вы можете прочитать в моем предыдущем посте ( http://www.lordofthejars.com/2015/10/gradle-and-java-ee.html ), как установить Gradle .

Чтобы написать интеграционные тесты для Java EE, де-факто инструментом является Arquillan. Если вы хотите узнать, что такое Arquillian , вы можете получить Руководство по началу работы в ( http://arquillian.org/guides/getting_started/ ) или в книге Arquillian In Action .

Чтобы начать использовать Arquillian , вам нужно добавить зависимости Arquillian , которые представлены в виде спецификации . Gradle не поддерживает артефакты спецификации из коробки, но вы можете использовать плагин Gradle -Management- plugin для поддержки определения спецификаций .

Более того, Gradle предлагает возможность добавлять больше исходных наборов тестов, помимо набора по умолчанию, который, как и в Maven, представляет собой src / test / java и src / test / resources . Идея состоит в том, что вы можете определить новый набор исходных тестов, в который вы собираетесь поместить все интеграционные тесты. При таком подходе каждый вид тестов четко разделен на разные исходные наборы. Вы можете написать Groovy- код в скрипте Gradle, чтобы достичь этого, или вы можете просто использовать gradle-testsets-plugin, это самый простой способ продолжить.

Поэтому для регистрации обоих плагинов (зависимостей и наборов тестов) вам необходимо добавить следующие элементы в файл сценария build.gradle :

01
02
03
04
05
06
07
08
09
10
11
12
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "io.spring.gradle:dependency-management-plugin:0.5.3.RELEASE"
        classpath 'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.2.0'
    }
}
 
apply plugin: "io.spring.dependency-management"
apply plugin: 'org.unbroken-dome.test-sets'

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

build.gradle с зависимостями Arquillian , TomEE и Java EE может выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
dependencyManagement {
    imports {
        mavenBom 'org.arquillian:arquillian-universe:1.0.0.Alpha1'
    }
}
 
dependencies {
    testCompile group: 'org.arquillian.universe', name: 'arquillian-junit', ext: 'pom'
    testCompile group: 'org.apache.openejb', name: 'arquillian-tomee-embedded', version:'1.7.2'
    testCompile group: 'junit', name: 'junit', version:'4.12'
    providedCompile group: 'org.apache.openejb',name: 'javaee-api', version:'6.0-6'
 
 
}

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

1
2
3
testSets {
    integrationTests
}

Где IntegrationTest — это имя набора тестов. testSets автоматически создает и настраивает следующие элементы:

  • src /grationTests / java и src /grationTests / resources в качестве допустимых папок с исходными наборами
  • Конфигурация зависимостей с именем integraTestsCompile , которая расширяется от testCompile , и другая, называемаяgrationTestRuntime, которая расширяется от testRuntime
  • Тестовое задание с именем integraTests, которое запускает тесты в наборе.
  • Задача Jar с именемgrationTestsJar, которая упаковывает тесты.

Обратите внимание, что вы можете изменить интеграцию с другими значениями, такими как intTests, и Gradle автоматически настроит предыдущие элементы на значение, установленное в testSets , например, src / intTests / java или, например, тестовая задача будет называться intTests .

Следующим шагом является создание интеграционных тестов с использованием Arquillian внутри набора тестовgrationTests . Например, тест Arquillian для проверки того, что вы можете POST-цвет в REST API, и он возвращается при вызове метода GET, будет выглядеть так:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@RunWith(Arquillian.class)
public class ColorServiceIntegrationTest {
 
    @Deployment
    public static WebArchive createDeployment() {
        return ShrinkWrap.create(WebArchive.class).addClasses(ColorService.class);
    }
 
    @ArquillianResource
    private URL webappUrl;
 
 
    @Test @RunAsClient
    public void postAndGet() throws Exception {
 
        // POST
        {
            final WebClient webClient = WebClient.create(webappUrl.toURI());
            final Response response = webClient.path("color/green").post(null);
 
            assertThat(response.getStatus(), is(204));
        }
 
        // GET
        {
            final WebClient webClient = WebClient.create(webappUrl.toURI());
            final Response response = webClient.path("color").get();
 
            assertThat(response.getStatus(), is(200));
 
            final String content = slurp((InputStream) response.getEntity());
 
            assertThat(content, is("green"));
        }
 
    }
 
    public static String slurp(final InputStream in) throws IOException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        final byte[] buffer = new byte[1024];
        int length;
        while ((length = in.read(buffer)) != -1) {
            out.write(buffer, 0, length);
        }
        out.flush();
        return new String(out.toByteArray());
    }
 
}

Теперь вы можете запустить интеграционные тесты, просто выполнив gradlew integrationTests

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

1
2
3
check.dependsOn integrationTest
 
integrationTest.mustRunAfter test

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

Так что теперь, когда вы запустите gradlew build , интеграционные тесты также будут выполнены.

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

01
02
03
04
05
06
07
08
09
10
11
task jacocoRootTestReport(type: JacocoReport) {
    sourceSets sourceSets.main
    executionData files([
            "$buildDir/jacoco/test.exec",
            "$buildDir/jacoco/integrationTests.exec"
    ])
    reports {
        xml.enabled false
        csv.enabled false
    }   
}

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

А для генерации отчетов вам нужно явно вызвать задачу jacocoRootTestReport при запуске Gradle .

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

Ссылка: Тесты Java EE, Gradle и Integration от нашего партнера JCG Алекса Сото в блоге One Jar To Rule All .