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

Как пропустить тесты в целях установки maven при запуске их в целях тестирования maven?

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

  • Если я запустил mvn install, я хочу, чтобы все тесты компилировались, но я не хочу их выполнять.
  • Если я запустил mvn test, я хочу, чтобы все тесты компилировались, но выполнялись только модульные тесты.
  • Если я запустил 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 будет выполнять только модульные тесты, но я не думаю, что это имеет большое значение.

4b9b3361

Ответ 1

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

  1. утверждать
  2. инициализировать
  3. генерировать-источники
  4. Процесс-источники
  5. генерировать-ресурсы
  6. Процесс-ресурсы
  7. компилировать
  8. Процесс-классы
  9. генерировать-тест-источников
  10. Процесс-тест-источники
  11. генерировать-тест-ресурсы
  12. Процесс-тест-ресурсы
  13. тест-компиляция
  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-plugin. Но вы должны знать, что если вы хотите вызвать интеграционные тесты, вы должны использовать следующую команду:

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), а не скомпилированными именами (.class). Я бы не использовал аннотацию Category, просто использование соглашений об именах делает pom проще и короче.

Ответ 3

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

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

совершенно справедливо и чрезвычайно легко достичь.
EDIT: кроме первого условия, которое действует снова в природе. Лучше всего здесь просто сделать 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 для тестов unit и интеграции (как уже говорилось в @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>

Ответ 4

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

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

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

Затем вы можете сделать:

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

Ответ 5

В maven-failafe-plugin docs есть раздел под названием "Пропуск по умолчанию".

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

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

<skipITs>true</skipITs>

Затем добавьте свойство skipTests в раздел plugin maven-failafe-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 по умолчанию будет выполнять модульные тесты, но не интеграционные тесты.

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

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

Ответ 6

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.

Ответ 7

Не указывайте этапы выполнения в конфигурации отказоустойчивого плагина. Например

    <plugins>
        <plugin>
            <artifactId>maven-failsafe-plugin</artifactId>
            <version>3.0.0-M3</version>
        </plugin>
    </plugins>

Теперь вам необходимо вызвать mvn failsafe: интеграционный тест для запуска интеграционных тестов; они будут пропущены в других целях mvn.