Подтвердить что ты не робот

Maven - развертывание webapp до tomcat перед тестом JUnit

У меня есть webapp, который предоставляет веб-сервис. Я хочу выполнить тесты JUnit с помощью SoapUI, чтобы проверить, работает ли эта служба должным образом.
Но для тестирования приложения веб-службы необходимо развернуть его на моем сервере Tomcat 7.

Я понятия не имею, как настроить maven для создания войны, а затем развернуть его на tomcat (в идеале: для запуска отдельного экземпляра tomcat для этого), а затем для запуска тестов JUnit.
Я буду признателен за любую помощь.

Я использую maven 2.2.1

4b9b3361

Ответ 1

Существует несколько школ мысли о том, как справиться с этим типом теста интеграции с Maven.

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

Теперь нет ничего плохого в использовании JUnit для запуска интеграционных тестов (хотя есть некоторые ограничения, которые вы можете поразить, например, модульные тесты не должны заботиться о последовательности отдельных тестов - если вы их правильно пишете, - поэтому JUnit обеспечивает это, не гарантируя какой-либо последовательности выполнения... до Java 1.7, порядок выполнения был случайно подразумевается порядком методов тестирования внутри класса, но он не был частью контракта JUnit... Некоторые люди переключаются на другие среды тестирования для их интеграционных тестов, например TestNG, если они находят, что unit test фокус JUnit мешает их разработке тестов)

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

Когда дело доходит до интеграционных тестов, есть две (и половина) школы мысли о правильном способе обработки тестов с Maven.

Школа 1 - Отказоустойчивость и integration-test/verify

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

НИКОГДА НИКОГДА НЕ РАБОТАЕТ mvn integration-test, так как это не приведет к неправильному срыву контейнера, в любое время, когда вы думаете, что хотите ввести mvn integration-test, вы действительно хотите набрать mvn verify (о, посмотрите, он короче и легче набирать... бонус)

Таким образом, вы делаете следующее:

Для дополнительных точек коричневого цвета вы должны использовать build-helper-maven-plugin: reserve-network-port, привязанный к фазе validate, чтобы убедитесь, что тестовый сервер запущен на неиспользуемом сетевом порту, а затем либо используйте фильтрацию ресурсов против тестовых ресурсов, чтобы передать порт через тесты, либо использовать системное свойство, переданное через systemPropertyVariables, чтобы номер порта был доступен для тестов.

Преимущества

  • Чистая сборка Maven
  • Если тесты не удались, вы не можете освободить проект
  • Могут переместить тесты интеграции в отдельный профиль (по соглашению run-its), если тесты слишком медленны для запуска каждой сборки.

Недостатки

  • Трудно выполнить тесты из среды IDE. Все интеграционные тесты начинаются/заканчиваются в IT, и хотя Maven знает, что запускать/заканчивать тесты с test с помощью Surefire и запускать тесты, начинающиеся/заканчивающиеся на IT с помощью Failsafe, ваша IDE, вероятно, этого не делает. Кроме того, ваша среда IDE не собирается запускать контейнер для вас, поэтому вам нужно выполнить много работы вручную, чтобы запустить тесты вручную.
  • Отладка тестов потенциально требует присоединения двух отладчиков, например. один для отладки приложения, запущенного в контейнере, а другой для отлаживать тестовые примеры.

    mvnDebug -Dmaven.failsafe.debug=true verify
    
  • Соединяет ваши тесты с процессом сборки Maven.

Школа 2 - Отдельный модуль

Эта школа мысли переводит тесты интеграции в отдельный модуль, который зависит от модуля war и копирует war в тестовые ресурсы, используя, например, dependency:copy-dependencies привязан к фазе generate-test-resources в сочетании с зависимостью Tomcat7 для тестирования.

сами тестовые сценарии запускают контейнер Tomcat7, используя встроенный режим

Преимущества

  • Тесты могут выполняться в среде IDE
  • Тесты интеграции отделены от модульных тестов, поэтому запрос IDE для запуска всех тестов не будет запускать более медленные тесты.

Недостатки

  • Артефакт war восстанавливается только в том случае, если вы проходите фазу package, следовательно, вам нужно периодически запускать не менее mvn clean package, чтобы обновить тестируемый код при использовании среды IDE.
  • Сбой интеграционных тестов не нарушает сборку модуля war, поэтому вы можете в конечном итоге освободить разбитый артефакт war, а затем завершить сборку реактора для тестового модуля интеграции. Некоторые люди противодействуют этой проблеме, имея тестовый модуль интеграции в src/it и используя Maven Invoker Plugin для запуска тестов... хотя это обеспечивает более низкую интеграцию с IDE, поэтому я не рекомендую эту строку.
  • Трудно получить консолидированный отчет по охвату тестов от Maven.
  • Нужно закодировать запуск/остановку контейнера из ваших тестовых случаев.

Школа 2.5 - Отказоустойчиво с тестовыми примерами, запускающими собственный сервер Tomcat7

Это своего рода гибрид двух подходов.

Вы используете Failsafe для выполнения тестов, но сами тесты несут ответственность за запуск и остановку контейнера Tomcat7, в который вы хотите протестировать.

Преимущества

  • Не нужно настраивать запуск/остановку сервера в Maven pom
  • IDE может безопасно запускать все тесты (хотя тесты интеграции могут быть более медленными, и вы можете не запускать их, но это не так, как будто все они потерпят неудачу, если не произойдет сбой теста)
  • Легче отлаживать тесты из вашей среды IDE (только один процесс для присоединения к нему, а среда IDE обычно упрощает отладку тестов, предоставляя специальный тестовый бегун).

Недостатки

  • Имейте в виду, что контейнер запускает/останавливает себя из ваших тестовых случаев.

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

Ответ 2

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

Эта конфигурация:

  • выполняет отдельные тесты отдельно от тестов интеграции. Он использует аннотацию @Category для корневых классов, которые расширяют модульные тесты и тесты интеграции.
  • перед интеграционными испытаниями запускается зависимое приложение (загружаемое как зависимость maven во время выполнения) на локальном компьютере, путем поиска открытого порта
  • после тестирования интеграции он сбрасывает зависимое приложение

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

Пока эта конфигурация работает потрясающе.

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>1.9.1</version>
            <executions>
                <execution>
                    <id>reserve-network-port</id>
                    <goals>
                        <goal>reserve-network-port</goal>
                    </goals>
                    <phase>pre-integration-test</phase>
                    <configuration>
                        <portNames>
                            <portName>tomcat.maven.http.port</portName>
                        </portNames>
                    </configuration>
                </execution>
                <execution>
                    <id>get-local-ip</id>
                    <goals>
                        <goal>local-ip</goal>
                    </goals>
                    <configuration>
                        <!-- if not given, 'local.ip' name is used -->
                        <localIpProperty>local.ip</localIpProperty>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <!-- http port from reserve-network-port-plugin-->
                <port>${tomcat.maven.http.port}</port>
                <!-- application path always starts with /-->
                <path>/</path>
                <webapps>
                    <webapp>
                        <groupId>com.company.other.app</groupId>
                        <artifactId>web-rest</artifactId>
                        <version>1.0.1-SNAPSHOT</version>
                        <type>war</type>
                        <contextPath>/webapi-loopback</contextPath>
                        <asWebapp>true</asWebapp>
                    </webapp>
                </webapps>
            </configuration>
            <executions>
                <execution>
                    <id>start-server</id>
                    <configuration>
                        <fork>true</fork>
                        <skip>${skipTests}</skip>
                        <systemProperties>
                            <spring.profiles.active>test,h2</spring.profiles.active>
                        </systemProperties>
                    </configuration>
                    <phase>pre-integration-test</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
                <execution>
                    <id>stop-server</id>
                    <configuration>
                        <skip>${skipTests}</skip>
                    </configuration>
                    <phase>post-integration-test</phase>
                    <goals>
                        <goal>shutdown</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.19</version>
            <configuration>
                <excludedGroups>com.company.app.service.IntegrationTestRootClassAnnotatedWithAtCategory</excludedGroups>
            </configuration>
            <executions>
                <execution>
                    <id>unit-test</id>
                    <phase>test</phase>
                    <goals>
                        <goal>test</goal>
                    </goals>
                    <configuration>
                        <argLine>-Xmx1024m -XX:MaxPermSize=256m @{jacocoArgLine}</argLine>
                        <excludedGroups> com.company.app.service.IntegrationTestRootClassAnnotatedWithAtCategory </excludedGroups>
                    </configuration>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <version>2.18</version>
            <dependencies>
                <dependency>
                    <groupId>org.apache.maven.surefire</groupId>
                    <artifactId>surefire-junit47</artifactId>
                    <version>2.18</version>
                </dependency>
            </dependencies>
            <executions>
                <execution>
                    <id>start-integration-test</id>
                    <phase>integration-test</phase>
                    <goals>
                        <goal>integration-test</goal>
                        <goal>verify</goal>
                    </goals>
                    <configuration>
                        <argLine>-Xmx1024m -XX:MaxPermSize=256m @{jacocoArgLine}</argLine>
                        <groups>com.company.app.IntegrationTestRootClassAnnotatedWithAtCategory</groups>
                        <includes>
                            <include>**/*.java</include>
                        </includes>
                        <systemPropertyVariables>
                            <program.service.url>
                                http://${local.ip}:${tomcat.maven.http.port}/webapi-loopback
                            </program.service.url>
                        </systemPropertyVariables>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Ответ 3

Как Стивен Коннолли объясняет, что нет прямого способа настроить это. Я объясню, как решить эту проблему с помощью защищенного плагина. В жизненном цикле maven тест может быть протестирован. Единичное тестирование одного из них и другого - интегрированное тестирование. Тестирование модулей может выполняться на этапе тестирования жизненного цикла maven. Когда вы хотите интегрировать тест, это можно сделать на этапе проверки. Если вы хотите узнать разницу между тестированием модулей и интегрировать тестирование, это хороший. По умолчанию unit test классы должны быть в ***/*Test.java и **/*TestCase.java в этом формате. Защищенный плагин будет искать **/IT*.java, **/*IT.java и **/*ITCase.java.

Вот пример. введите описание изображения здесь

Здесь у меня есть один класс unit test и один интегрированный тестовый класс. Теперь я объясню, как выглядит выглядит как maven pom.xml. Строка раздела конфигурации maven должна выглядеть так.

<build>
    <plugins>
        <plugin>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.3</version>
            <configuration>
                <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
                <warName>${name}</warName>
                <outputDirectory>/home/jobs/wso2/wso2as-5.3.0/repository/deployment/server/webapps</outputDirectory>
                <goal>
                </goal>
            </configuration>
        </plugin>

        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <version>2.12.4</version>
            <executions>
                <execution>
                    <id>integration-test</id>
                    <goals>
                        <goal>integration-test</goal>
                        <goal>verify</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>

Перед развертыванием веб-приложения (файл войны) запускаются юнит-тесты. Но интегральные тесты выполняются на этапе проверки. Надеюсь, ваше требование будет удовлетворено на этом этапе.