Как я могу пропустить тесты в maven install goal, запустив их в maven test goal?


У меня есть многомодульный проект maven с интеграционными и модульными тестами в одной папке (src/test/java). Интеграционные тесты помечаются знаком @Category(IntegrationTest.class). Я хочу закончить со следующей установкой:

  1. Если я запускаю mvn install, я хочу, чтобы все тесты были скомпилированы,но я не хочу их выполнять.
  2. если я запускаю mvn test, я хочу, чтобы все тесты компилировались, но выполнялись только модульные тесты.
  3. если я запускаю mvn integration-test, я хочу скомпилировать и выполнить все тесты.

Важное дело в том, что я хочу, чтобы это было настроено в pom.xml без каких-либо дополнительных аргументов командной строки.

В настоящее время я придумал следующую настройку в моем родительском pom.xml, где единственной проблемой является #1, где выполняются все тесты:

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${project.java.version}</source>
                    <target>${project.java.version}</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.14.1</version>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.surefire</groupId>
                        <artifactId>surefire-junit47</artifactId>
                        <version>2.14.1</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <includes>
                        <include>**/*.class</include>
                    </includes>
                    <excludedGroups>cz.cuni.xrg.intlib.commons.IntegrationTest</excludedGroups>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.14.1</version>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.surefire</groupId>
                        <artifactId>surefire-junit47</artifactId>
                        <version>2.14.1</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <groups>cz.cuni.xrg.intlib.commons.IntegrationTest</groups>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                        <configuration>
                            <includes>
                                <include>**/*.class</include>
                            </includes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

Все дочерние модули имеют следующую конфигурацию плагина в своем pom.xml, который, как я полагаю, должен наследовать от родительского pom:

<build> 
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
        </plugin>

        <plugin>
            <artifactId>maven-failsafe-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Я пробовал использовать <skipTests>true</skipTests>, но он отключает выполнение тестов для всех целей, а это не то, что я хочу (нарушает правила № 2 и №3). Также довольно странно, что mvn test чтит вариант skipTests=true...с чего бы мне вообще захотеть его запустить??

После нескольких часов поиска в гугле и пробования различных комбинаций я сомневаюсь, можно ли вообще не запускать тесты в mvn install, в то же время выполняя их в mvn test. Надеюсь, кто-нибудь докажет, что это не так. ;) Я также готов принять решение, в котором mvn install будет выполняться только модульные тесты, но я не думаю, что это имеет большое значение.
6 46

6 ответов:

Похоже, вы не поняли концепциюжизненного цикла сборки в Maven. Если вы запускаете mvn install все фазы жизненного цикла (включая саму фазу install), запускаются до фазы установки. Это означает выполнение следующих действий фазы:

  1. проверить
  2. инициализировать
  3. генерация-источники
  4. процесс-источники
  5. generate-resources
  6. процесс-ресурсы
  7. компиляция
  8. классы процессов
  9. generate-test-sources
  10. процесс-тест-источники
  11. generate-test-resources
  12. процесс-тест-ресурсы
  13. test-compile
  14. процесс-тест-классы
  15. тест
  16. подготовка пакета
  17. пакет
  18. предварительный интеграционный тест
  19. интеграционный тест
  20. постинтеграционный тест
  21. проверить
  22. установить

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

Это может быть достигнуто с помощью профиля в Maven:

 <project>
  [...]
  <profiles>
    <profile>
      <id>no-unit-tests</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
              <skipTests>true</skipTests>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
  [...]
</project>

Итак, ваше первое требование:

  1. Если я запускаю mvn install, я хочу, чтобы все тесты были скомпилированы,но я не хочу их выполнять.

Может быть достигнуто с помощью следующего:

mvn -Pno-unit-test test
  1. Если я бегу mvn test, я хочу все тесты компилируются, но выполняются только модульные тесты.

Это может быть просто достигнуто с помощью простого вызова:

mvn test

Причина, по которой не выполняется этап интеграционных тестов (см. Жизненный цикл сборки).

  1. если я запускаю mvn integration-test, я хочу скомпилировать и выполнить все тесты.

Это означает запуск по умолчанию, который включает в себя запуск фазы test, которая будет запускать модульные тесты (maven-surefire-plugin) и, кроме того, запуск интеграционного теста, которые обрабатываются по Maven-failsafe-плагину. Но вы должны знать, что если вы хотите вызвать интеграционные тесты, вы должны использовать следующую команду:

mvn verify

Вместо этого, потому что вы пропустили фазу post-integration-test в вашем предыдущем вызове.

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

<includes>
 <include>**/*Test*.java</include>
 <include>**/*Test.java</include>
 <include>**/*TestCase.java</include>
</includes>

И интеграционные тесты должны называться так: следующее:

<includes>
 <include>**/IT*.java</include>
 <include>**/*IT.java</include>
 <include>**/*ITCase.java</include>
</includes>

Я надеюсь, что вы настроили Maven-failsafe-plugin следующим образом, который необходим для привязки Maven-failsafe-plugin к правильным фазам жизненного цикла:

<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>2.15</version>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  [...]
</project>

Как вы правильно сделали, но вы должны знать, что теги include работают с исходным кодом (.java), а не на скомпилированных именах (.класс). Я бы не стал использовать аннотацию категории, просто использование соглашений об именовании делает pom проще и короче.

В соответствии с отказоустойчивой документацией плагина

mvn install -DskipITs

Это то, что вы хотите.

Что заявил ОП в своем вопросе:

Если я запускаю mvn install , я хочу, чтобы все тесты компилировались, но я не хочу казнить любого.
Если я запускаю mvn test , я хочу, чтобы все тесты компилировались, но выполнялись только модульные тесты.
Если я запускаю mvn integration-test , я хочу скомпилировать и выполнить все тесты.

Является совершенно действительным и чрезвычайно легко достижимым.
правка: кроме первого условия, которое действует против природы maven. Лучший способ здесь был бы просто сделать mvn install -DskipTests

Все, что вам нужно, это следующий фрагмент в pom.xml:

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

И придерживатьсяMaven соглашений об именовании для модульных и интеграционных тестов (как уже говорилось @khmarbaise). Поэтому обычно называют интеграционные тесты с помощью IT (например, MyIntegrationTestIT.java) и позволяют maven-failsafe выполнять свою работу.
Таким образом, вам даже не нужны категории JUnit (хотя иногда они могут быть весьма полезны).

Вот и все :)

  • mvn test выполняет только модульные тесты
  • mvn integration-test выполняет все тесты
  • mvn failsafe:integration-test запускает только интеграционные тесты
  • mvn clean verify когда вы хотите быть уверены, что весь этот проект просто работает


Некоторые личные советы

Хранение интеграционных тестов отдельно от модульных тестов позволяет легко запускать в среде IDE все тесты в некотором пакете. Обычно используется дополнительный каталог test-integration (или integrationtest). для этой цели.
Этого также легко достичь с maven:

<plugin>
    <!-- adding second test source directory (just for integration tests) -->
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>1.9.1</version>
    <executions>
        <execution>
            <id>add-integration-test-source</id>
            <phase>generate-test-sources</phase>
            <goals>
                <goal>add-test-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>src/test-integration/java</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

А затем переместите интеграционные тесты в этот каталог. Это должно выглядеть так:

src
   main
   test
   test-integration

Интеграционные тесты обычно требуют больше памяти:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    ...
    <configuration>
        <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine>
    </configuration>
</plugin>

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

В основном, то, что вы делаете,-это определяете профиль и помещаете весь свой xml-код, связанный с интеграционными тестами, в этот профиль. Чем вы активируете его, когда свойство -DskipIntegrationTests отсутствует.

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

Тогда вы могли бы сделать:

mvn install -DskipIntegrationTests -DskipUnitTests # (runs install without any tests)
mvn test # (runs unit tests)
mvn post-integration-test # (runs all tests)

Maven-failsafe-plugindocs имеет раздел под названием "Пропуск по умолчанию."

К сожалению, шаги, описанные на странице, не работают так, как написано. Однако небольшое изменение этих шагов заставит его работать:

В разделе properties раздела pom.xml добавьте следующее:

<skipITs>true</skipITs>

Затем добавьте СВОЙСТВО skipTests в раздел plugin Maven-failsafe-plugin:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <configuration>
        <skipTests>${skipITs}</skipTests>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
        </execution>
    </executions>
</plugin>

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

Но an mvn install -DskipITs=false будет выполнять как модульные тесты, так и интеграционные тесты.

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

mvn test-compile делает именно то, что вы ищете. Вы можете просто заменить mvn install на mvn test-compile, и все готово. Нет необходимости настраивать файл pom или что-то еще. Ниже связанный вопрос аналогичен вокруг #1:

Maven-как компилировать тесты без их запуска ?

mvn test-compile следует принять как лучший ответ, поскольку Maven поддерживает именно то, что вы хотите сделать изначально и без всякой магии. Вы бы закончили так:

If I run mvn test-compile, I want all tests to compile, but I do not want to execute any.
If I run mvn test, I want all tests to compile, but execute only unit tests.
If I run mvn integration-test, I want to compile and execute all tests.