Объединение профилей в Maven для пропуска нескольких категорий модульных тестов?

У меня проблема с попыткой настроить Maven для исключения некоторых категорий модульных тестов на основе нескольких профилей.

У меня есть две категории, определенные для модульного тестирования: SlowTest для тех модульных тестов, выполнение которых занимает очень много времени, и WindowsTest для тех модульных тестов, которые могут выполняться только в среде Windows.

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

<profiles>
  <!-- Exclude any tests in `SlowTest` category when profile 'skipSlowTests' is specified. -->
  <profile>
    <id>skipSlowTests</id>
    <activation>
      <activeByDefault>false</activeByDefault>
    </activation>
    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <configuration>
            <excludedGroups>SlowTest.class</excludedGroups>
          </configuration>
        </plugin>
      </plugins>
    </build>
  </profile>  

  <!-- Skip any tests in 'WindowsTest' category when not running on Windows. -->
  <profile>
    <id>skipWindowsTests</id>
    <activation>
      <os><family>!windows</family></os>
    </activation>
    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <configuration>
            <excludedGroups>WindowsTest.class</excludedGroups>
          </configuration>
        </plugin>
      </plugins>
    </build>
  </profile>  

</profiles>

Так, например, когда я хочу запустить тесты и исключить любые медленные тесты, я могу выполнить mvn -PskipSlowTests test. И если я хочу пропустить какие-либо тесты Windows, я могу выполнить mvn test в ОС, отличной от Windows (или явно указать -PskipWindowsTests в командной строке).

Проблема здесь в том, что когда оба профиля skipSlowTests и skipWindowsTests активированы, пропускаются только тесты Windows. Медленные тесты продолжают работать. Когда maven создает эффективный файл pom.xml, он применяет профиль skipSlowTests и настраивает maven-surefire-plugin для исключения групп SlowTest.class. Затем применяется профиль skipWindowsTests, и это заменяет исключенные группы на WindowsTest.class.

Я действительно хочу, чтобы исключенные группы были SlowTest.class,WindowsTest.class, когда оба профиля активированы, но я не могу найти способ сделать это.

Я не могу видеть в maven добавление значения к свойству, например.

<properties>
  <excludedGroups>IgnoreTest.class</excludedGroups>
</properties>

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <excludedGroups>${excludedGroups}</excludedGroups>
  </configuration>
</plugin>

<profile>
  <id>skipSlowTests</id>
  <property>
    <excludedGroups>${excludedGroups},SlowTest.class</excludedGroups>
  </property>
  ...
</profile>

<profile>
  <i>skipWindowsTests</id>
  <property>
    <excludedGroups>${excludedGroups},WindowsTest.class</excludedGroups>
  </property>
  ...
</profile>

Это pom.xml не работает, потому что есть рекурсия при присвоении значения свойству excludedGroups.

И нет возможности настроить третий профиль (например, skipSlowTestsAndWindowsTests), который активируется всякий раз, когда активируются и skipSlowTests, и skipWindowsTests.

Любые предложения здесь? Может быть, добавить отдельные фазы в maven-surefire-plugin (одну для медленных тестов, одну для тестов Windows, одну для всех остальных) и использовать профили для определения, какие фазы выполняются?

Изменить №1

Я попытался создать отдельные фазы выполнения для maven-surefire-plugin следующим образом:

<!-- By default, do not skip slow tests or windows tests -->
<properties>
  <skipSlowTests>false</skipSlowTests>
  <skipWindowsTests>false</skipWindowsTests>
</properties>

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <executions>
    <!-- Default execution will skip SlowTest and WindowsTest categories -->
    <execution>
      <id>default-test</id>
      <phase>test</phase>
      <goals>
        <goal>test</goal>
      </goals>
      <configuration>
        <excludedGroups>SlowTest,WindowsTest</excludedGroups>
      </configuration>
    </execution>
    <!-- Slow Test execution will run the slow tests only (if not skipped) -->
    <execution>
      <id>slow-test</id>
      <phase>test</phase>
      <goals>
        <goal>test</goal>
      </goals>
      <configuration>
        <skip>${skipSlowTests}</skip>
        <groups>SlowTest</groups>
      </configuration>
    </execution>
    <!-- Windows Test execution will run the windows tests only (if not skipped) -->
    <execution>
      <id>windows-test</id>
      <phase>test</phase>
      <goals>
        <goal>test</goal>
      </goals>
      <configuration>
        <skip>${skipWindowsTests}</skip>
        <groups>WindowsTest</groups>
      </configuration>
    </execution>
  </executions>
</plugin>

<profiles>
  <!-- Skip slow tests when skipSlowTests profile enabled -->
  <profile>
    <id>skipSlowTests</id>
    <properties>
      <skipSlowTests>true</skipSlowTests>
    </properties>
  </profile>
  <!-- Skip windows tests when skipWindowsTests profile enabled -->
  <profile>
    <id>skipWindowsTests</id>
    <properties>
      <skipWindowsTests>true</skipWindowsTests>
    </properties>
    ...
  </profile>
</profiles>

Эта конфигурация будет запускать тесты в трех отдельных исполнениях: выполнение default-test будет запускать все тесты, кроме медленных тестов и тестов Windows; выполнение slow-test будет запускать только медленные тесты; и выполнение windows-test будет запускать только тесты Windows. А если включены оба профиля skipSlowTests и skipWindowsTests, то и медленные тесты, и тесты windows будут пропущены.

Проблема здесь в том, что есть тест, помеченный как категориями SlowTest, так и WindowsTest:

@Test @Category({SlowTest.class,WindowsTest.class})
public void slowWindowsTestCase() { ... }

Когда включен только профиль skipSlowTests, выполнение windows-test все равно выполняется, а поскольку метод slowWindowsTestCase помечен как тест Windows, он будет выполняться, даже если мы хотим пропустить медленные тесты. Точно так же этот тестовый пример также будет выполняться, когда включен только профиль skipWindowsTests. Единственный способ пропустить этот тестовый пример — указать профили skipSlowTests и skipWindowsTests.

Я попытался изменить выполнение следующим образом:

    <execution>
      <id>slow-test</id>
        ... 
        <groups>SlowTest</groups>
        <excludedGroups>WindowsTest</excludedGroups>
        ...
    </execution>
    <execution>
      <id>windows-test</id>
        ... 
        <groups>WindowsTest</groups>
        <excludedGroups>SlowTest</excludedGroups>
        ...
    </execution>

Но теперь метод slowWindowsTestCase никогда не выполняется.

Редактировать №2

И даже если бы я мог заставить выполнение тестов работать правильно, мне нужно было бы добавить зависимость от maven-surefire-plugin, чтобы интерфейсы SlowTest и WindowsTest могли загружаться во время тестирования. Я поместил maven-surefire-plugin в раздел pluginManagement моего родительского POM, но любая зависимость, определенная для этого плагина, не может иметь область действия test. В результате запустить тест вне модуля, определяющего интерфейсы SlowTest и WindowsTest, не получится. Я могу добавить зависимость области видимости test для плагина в профилях, но это не будет охватывать случай, когда ни один профиль не активен.


person John Q Citizen    schedule 07.11.2013    source источник
comment
Интересный сценарий. Согласны ли вы с тем, что проблема коренится в синтаксисе <excludedGroups>: это должен быть не тип String, а скорее Array, например. <excludedGroups><excludedGroup>A</excludedGroup><excludedGroup>B</excludedGroup></excludedGroups>. Теперь можно легко объединять элементы в один список. Вы можете запустить задачу для улучшения.   -  person dma_k    schedule 31.01.2014


Ответы (2)


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

person Matthieu Bertin    schedule 10.08.2015

Как насчет того, чтобы каждый профиль определял свойство excludedGroups и объединял их в одно свойство в самом начале выполнения POM?

<build>
  ...
  <plugin>
    <groupId>org.codehaus.gmavenplus</groupId>
    <artifactId>gmavenplus-plugin</artifactId>
    <version>1.6</version>
    <dependencies>
      <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.4.9</version>
        <scope>runtime</scope>
      </dependency>
    </dependencies>
    <executions>
      <execution>
        <id>excludedGroups</id>
        <phase>initialize</phase>
        <goals>
          <goal>execute</goal>
        </goals>
        <configuration>
          <scripts>
            <script>
              <![CDATA[
              def groups = ""
              (project.activeProfiles).each{ profile -> groups += profile.properties.excludedGroups + "," }
              project.properties.excludedGroups = groups.substring(0, groups.length() - 1)
              ]]>
            </script>
          </scripts>
        </configuration>
      </execution>
    </executions>
  </plugin>
</build>

<profiles>
  <!-- Exclude any tests in `SlowTest` category when profile 'skipSlowTests' is specified. -->
  <profile>
    <id>skipSlowTests</id>
    <properties>
      <excludedGroups>SlowTest.class</activeByDefault>
    </properties>
  </profile>  

  <!-- Skip any tests in 'WindowsTest' category when not running on Windows. -->
  <profile>
    <id>skipWindowsTests</id>
    <activation>
      <os><family>!windows</family></os>
    </activation>
    <properties>
      <excludedGroups>WindowsTest.class</excludedGroups>
    </properties>
  </profile>
</profiles>

Теперь вы можете использовать ${excludedGroups} в качестве значения для конфигурации плагина surefire.

person Roberto Lo Giacco    schedule 11.10.2017