Статьи

Измерение общего охвата кода в многомодульном проекте Maven


К сожалению, как мы знаем, Maven не имеет встроенной поддержки для различных типов тестов. На самом деле существует мало открытых заявок на адаптацию Maven к различным стратегиям тестирования, таким как добавлениеgrationTestSourceDirectory к модели POM (
MNG-2009 ) или новые фазы жизненного цикла для работы с источниками тестов интеграции (
MNG-2010 ), чтобы заменить необходимость использования build-helper- Maven-плагин.

Но кроме отделения различных тестов друг от друга, как мы можем использовать доступные механизмы для вызова как модульных, так и интеграционных тестов и измерения их покрытия кода? Я хочу добиться такой ситуации (возможно, за исключением количества тестов, потому что я обычно хочу иметь немного больше :)) на 
 панели инструментов
Sonar :

Первое, что мы должны сделать, это включить соответствующий плагин Sonar. Для этого просто нажмите «Настроить виджеты» на панели инструментов, выберите пункт «Покрытие интеграционных тестов» и поместите его в соответствующую позицию.

Мы будем работать над простым проектом Maven с популярным макетом:

Оба модуля содержат два «производственных» класса: один для тестирования с использованием модульных тестов, а другой для интеграционного тестирования. Структура проекта выглядит следующим образом (надеюсь, имена классов довольно очевидны):

Теперь пришло время настроить наш проект так, чтобы он соответствовал подходящему инструменту измерения покрытия. Я предпочитаю 
JaCoCo,  потому что он хорошо интегрирован с Sonar и может быть адаптирован для работы с различными типами тестов. В качестве основы тестирования мы будем использовать
TestNG . Итак, давайте добавим к нашему мастеру pom.xml следующие зависимости:

   <dependencies>
    <dependency>
      <groupid>org.testng</groupid>
      <artifactid>testng</artifactid>
      <version>6.7</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupid>org.jacoco</groupid>
      <artifactid>org.jacoco.core</artifactid>
      <version>0.6.2.201302030002</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

В TestNG мы можем объединять тесты в группы, используя
@Test (group = «groupName») , и мы собираемся использовать эту функциональность и использовать группу «unit» для всех модульных тестов и группу «int» для интеграционных.

Мы также должны установить свойства сонара:

  <properties>
    <!-- select JaCoCo as a coverage tool -->
    <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
    <!-- force sonar to reuse reports generated during build cycle -->
    <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
    <!-- set path for unit tests reports -->
    <sonar.jacoco.reportPath>${project.basedir}/target/jacoco-unit.exec</sonar.jacoco.reportPath>
    <!-- all modules have to use the same integration tests report file -->
    <sonar.jacoco.itReportPath>${project.basedir}/../target/jacoco-it.exec</sonar.jacoco.itReportPath>
  </properties>

Следующее, что нам нужно сделать, это настроить плагины Maven. К стандартной верной конфигурации мы добавим исключение из группы «int»:

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.14</version>
        <configuration>
          <excludedGroups>int</excludedGroups>
        </configuration>
      </plugin>

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

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>2.14</version>
        <configuration>
          <!-- property set by jacoco-maven-plugin -->
          <argLine>${itCoverageAgent}</argLine>
          <groups>int</groups>
          <!-- by default only IT*, *IT and *ITCase classes are included -->
          <includes>
            <include>**/*.java</include>
          </includes>
        </configuration>
        <executions>
          <execution>
            <id>integration-test</id>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

Последний шаг — добавление плагина jacoco:

      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.6.2.201302030002</version>
        <executions>
          <!-- prepare agent for measuring unit tests -->
          <execution>
            <id>prepare-unit-tests</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
            <configuration>
              <destFile>${sonar.jacoco.reportPath}</destFile>
            </configuration>
          </execution>

          <!-- prepare agent for measuring integration tests -->
          <execution>
            <id>prepare-integration-tests</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
            <phase>pre-integration-test</phase>
            <configuration>
              <destFile>${sonar.jacoco.itReportPath}</destFile>
              <propertyName>itCoverageAgent</propertyName>
            </configuration>
          </execution>
        </executions>
      </plugin>

Теперь вызовите нормальную сборку maven (набрав
mvn clean install ). В выводе компиляции мы видим, что плагин JaCoCo вызывается как для модуля

[INFO] — jacoco-maven-plugin: 0.6.2.201302030002: prepare-agent (prepare-unit-tests) @ first —

и интеграционных тестов

[ INFO] — jacoco-maven-plugin: 0.6.2.201302030002: prepare-agent (prepare-интеграционные тесты) @ first —

Пока сборка завершена успешно, мы можем приступить к запуску сонара:
mvn sonar: sonar

Надеюсь, все прошло нормально и теперь вы можете любоваться хорошо измеренным покрытием кода на панели управления Sonar!