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

Cobertura на мультимодульном проекте maven

У меня есть проект Maven с 4 модулями - 3 из них содержат код и некоторые тесты (тестирование равно и хэш-код классов), тогда как 4-й модуль предназначен для тестирования 3 других модулей.

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

Я прочитал некоторые ссылки, такие как SeamTestCoverageWithCobertura и Использование плагина Coverage в мультимодульном Maven 2, но должно быть решение из коробки. Кто-нибудь может сообщить какие-то новые направления в этой теме? Или есть более простые инструменты, такие как cobertura? Я наткнулся на emma, но этот инструмент не предлагает покрытие линии...

4b9b3361

Ответ 1

Начиная с версии 2.6 существует опция aggregate, которая может быть установлена ​​в true в родительском pom:

<reporting>
<plugins>
  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>cobertura-maven-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <outputDirectory>./target/tmpCobertura</outputDirectory>
        <formats>
            <format>html</format>
        </formats>
        <aggregate>true</aggregate>
    </configuration>
  </plugin>
</plugins>
</reporting>

Ответ 2

У нас нет сонара здесь и сейчас, мы не можем его установить. Поэтому мне пришлось найти обходное решение и получить его. Это решение работает с простым mvn clean install -DrunCobertura=true в проекте с несколькими модулями. Вам нужно добавить этот профиль в свой super pom.xml вашего проекта, определить свойство working.dir, и он должен работать.

<profile>
    <id>runCobertura</id>
    <activation>
        <property>
            <name>runCobertura</name>
            <value>true</value>
        </property>
    </activation>
    <properties>
        <cobertura.format>html</cobertura.format>
        <cobertura.working.dir>${working.dir}/${project.version}/cobertura</cobertura.working.dir>
        <cobertura.complete.ser.file>${cobertura.working.dir}/complete.ser</cobertura.complete.ser.file>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.4.1</version>
                <inherited>false</inherited>
                <configuration>
                    <filesets>
                        <fileset>
                            <directory>.</directory>
                            <includes>
                                <include>cobertura.ser</include>
                            </includes>
                        </fileset>
                        <fileset>
                                <directory>${cobertura.working.dir}</directory>
                            </fileset>
                    </filesets>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.7</version>
                <executions>
                    <execution>
                        <id>cobertura-Instrument</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <taskdef resource="tasks.properties"/>
                                <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                <if>
                                    <available file="${project.build.outputDirectory}"/>
                                    <then>
                                        <cobertura-instrument>
                                            <fileset dir="${project.build.outputDirectory}">
                                                <include name="**/*.class"/>
                                            </fileset>
                                        </cobertura-instrument>
                                    </then>
                                </if>
                            </target>
                        </configuration>
                    </execution>
                    <execution>
                        <id>cobertura-createCombinedSerFile</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <taskdef resource="tasks.properties"/>
                                <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                <if>
                                    <available file="${cobertura.complete.ser.file}"/>
                                    <then>
                                        <cobertura-merge datafile="${basedir}/tmp.ser">
                                            <fileset file="${cobertura.complete.ser.file}"/>
                                            <fileset file="${basedir}/cobertura.ser"/>
                                        </cobertura-merge>
                                        <move file="${basedir}/tmp.ser" tofile="${basedir}/cobertura.ser"/>
                                    </then>
                                </if>
                            </target>
                        </configuration>
                    </execution>
                    <execution>
                        <id>cobertura-copyResultSerFileAndSources</id>
                        <phase>test</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <taskdef resource="tasks.properties"/>
                                <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                <if>
                                    <available file="${basedir}/cobertura.ser"/>
                                    <then>
                                        <move file="${basedir}/cobertura.ser" tofile="${cobertura.complete.ser.file}"/>
                                        <mkdir dir="${cobertura.working.dir}/source"/>
                                        <if>
                                            <available file="${basedir}/src/main/java"/>
                                            <then>
                                                <copy todir="${cobertura.working.dir}/source">
                                                    <fileset dir="src/main/java">
                                                        <include name="**/*.java"/>
                                                    </fileset>
                                                </copy>
                                            </then>
                                        </if>
                                        <cobertura-report datafile="${cobertura.complete.ser.file}" format="${cobertura.format}" destdir="${cobertura.working.dir}/report">
                                            <fileset dir="${cobertura.working.dir}/source"/>
                                        </cobertura-report>
                                    </then>
                                </if>
                            </target>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>net.sourceforge.cobertura</groupId>
                        <artifactId>cobertura</artifactId>
                        <version>1.9.4.1</version>
                    </dependency>
                    <dependency>
                        <groupId>ant-contrib</groupId>
                        <artifactId>ant-contrib</artifactId>
                        <version>20020829</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>net.sourceforge.cobertura</groupId>
            <artifactId>cobertura</artifactId>
            <version>1.9.4.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</profile>

Что он делает:

1. @process-classes -Инструментируйте скомпилированные классы модуля.

2. @generate-test-sources -Выражает файл .ser из предыдущих модулей с созданным одним из этого модуля, чтобы получить полный охват кода.

3. @test -Создает отчет о покрытии кода. Должен быть вызван в последнем модуле, но из-за того, что последний модуль может меняться, я вызываю его всегда, а предыдущие отчеты будут перезаписаны. Если вы используете отчет в формате xml (для Дженкинса), это быстро, поэтому это не имеет значения.

Ответ 3

Согласно MCOBERTURA-65, плагин maven cobertura все еще не знает как объединить отчеты о подмодулях в консолидированный. Некоторая работа была выполнена для реализации цели merge на плагине maven cobertura (см. MCOBERTURA-33), но этот код еще не включен в плагин. Я сам не тестировал патч и не могу сказать, стоит ли попробовать.

В результате многие люди действительно предлагают использовать плагин maven , но я лично останусь далеко от него, поскольку он не "t очень удовлетворительно в долгосрочной перспективе, и я столкнулся с множеством проблем с ним (технические проблемы, потеря истории,...). Вместо этого я рекомендую Sonar. Посмотрите Nemo, публичный экземпляр последней версии Sonar, для живой демонстрации этого инструмента. См. Например, проект Commons Digester и просветление покрытия кода.

Ответ 5

Я бы очень хотел поблагодарить Свена Оппермана за представление его профиля профиля runCobertura. Это помогло я решаю вопрос о том, "как вы получаете сводные отчеты о покрытии для многомодульных проектов, когда вы не можете быть способный использовать Сонар.

Я создал пример, который демонстрирует, как создавать многомодульные проекты, которые создают отчеты о покрытии кода, которые оценивают не только охват unit test (во всех подмодулях), но также и охват INTEGRATION TESTS THAT BRING ВВЕРХ ВАШЕ ЗАЯВЛЕНИЕ В КАЧЕСТВЕ .WAR IN JETTY. Пример размещен здесь:

        http://dl.dropbox.com/u/9940067/code/multi-module-cobertura.zip 

Рецепт, который я предоставляю, можно использовать повторно, если вы скопируете профиль runCobertura, указанный ниже (на основе одного предоставить Свен.)

Вот некоторые примечания, которые помогут вам использовать этот профиль:

* the integration test module that launches jetty (and defines tests that run against 
  the production .war) must either be named web-test-driver-for-code-coverage, or you 
   must modify the <if> statements in the runCobertura configuration block.

* your coverage reports will appear wherever you set your <working.dir> variable

* you MUST include 'clean' on the command line when you run your build for code coverage. 'clean' 
  will blow away prior cobertura.ser files, 
  which if left lurking around can cause very confusing reports to be 
   generated (a sign you need to 'clean' is that the reports show 
  100% coverage for everything, including stuff you know is never called.

            mvn -PrunCobertura clean install      # gives you the aggregate reports.



* the module  web-test-driver-for-code-coverage defines a servlet context listener that explicitly flushes the cobertura metrics to disk
  when the web server shuts down.  Supposedly the container is supposed to do this automatically, but that didn't work for me, so 
  I had to hook in the explicit call to flush out the metrics.

* the integration tests are done in groovy because i based this on some maven project skeletons that already used groovy.
  Sorry for the added clutter, but it does show you how to do your tests in groovy (which is highly recommended anyway.)

* Note that when you compile with the runCobertura  profile all of your artifacts are created with cobertura instrumentation, even your 
  .war file.  You NEVER want to let this get out in production of course (for one thing it would run realllll slow.)  I have not 
  yet figured out a food way to get the artifacts to rename themselves so that the 'cobertura-ness' is obvious.



    <profiles>
    <profile>
        <id>runCobertura</id>
        <activation>
            <property>
                <name>runCobertura</name>
                <value>true</value>
            </property>
        </activation>
        <properties>
            <cobertura.format>html</cobertura.format>
            <working.dir>/tmp</working.dir>
            <cobertura.working.dir>${working.dir}/${project.version}/cobertura</cobertura.working.dir>
            <cobertura.complete.ser.file>${cobertura.working.dir}/complete.ser</cobertura.complete.ser.file>

            <!-- scope which determines whether or not cobertura is included in .war file: overriden here -->
            <cobertura.dependency.scope>compile</cobertura.dependency.scope>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>2.4.1</version>
                    <inherited>false</inherited>
                    <configuration>
                        <filesets>
                            <fileset>
                                <directory>.</directory>
                                <includes>
                                    <include>**/cobertura.ser</include>
                                </includes>
                            </fileset>
                            <fileset>
                                    <directory>${cobertura.working.dir}</directory>
                                </fileset>
                        </filesets>
                    </configuration>
                </plugin>




                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <version>1.7</version>
                    <executions>
                        <execution>
                            <id>cobertura-Instrument</id>
                            <phase>process-classes</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <target>
                                    <taskdef resource="tasks.properties"/>
                                    <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                    <echo message="::PROCESS CLASSES: ${artifactId}"/>

                                    <if>
                                      <equals arg1="${artifactId}" arg2="web-test-driver-for-code-coverage" />
                                        <then>
                                            <echo message="::SKIPPING PHASE for integration test"/>
                                        </then>
                                        <else>
                                            <if>
                                                <available file="${project.build.outputDirectory}"/>
                                                <then>
                                                    <echo message="::BEFORE INSTRUMENT"/>
                                                    <cobertura-instrument>
                                                        <fileset dir="${project.build.outputDirectory}">
                                                            <include name="**/*.class"/>
                                                        </fileset>
                                                    </cobertura-instrument>
                                                </then>
                                            </if>
                                        </else>
                                    </if>


                                </target>
                            </configuration>
                        </execution>
                        <execution>
                            <id>cobertura-createCombinedSerFile</id>
                            <phase>generate-test-sources</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <target>
                                    <taskdef resource="tasks.properties"/>
                                    <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                    <echo message=":::generate-test-sources"/>


                                    <if>
                                      <equals arg1="${artifactId}" arg2="web-test-driver-for-code-coverage" />
                                        <then>
                                            <echo message="::SHORT CIRCUIT COMBINE PHASE for integration test"/>
                                            <echo  message="source - ${cobertura.complete.ser.file} dest - ${basedir}/cobertura.ser"/>
                                            <copy file="${cobertura.complete.ser.file}" tofile="${basedir}/cobertura.ser"/>
                                        </then>
                                        <else>
                                            <if>
                                                <available file="${basedir}/cobertura.ser"/>
                                                <then>
                                                    <echo message="::: Is available ${basedir}/cobertura.ser"/>
                                                </then>
                                            </if>

                                            <if>
                                                <available file="${cobertura.complete.ser.file}"/>
                                                <then>
                                                    <echo message="before merge1"/>
                                                    <cobertura-merge datafile="${basedir}/tmp.ser">
                                                        <fileset file="${cobertura.complete.ser.file}"/>
                                                        <fileset file="${basedir}/cobertura.ser"/>
                                                    </cobertura-merge>
                                                    <echo message="move temp.ser to ${basedir}/cobertura.ser"/>
                                                    <move file="${basedir}/tmp.ser" tofile="${basedir}/cobertura.ser"/>
                                                </then>
                                            </if>
                                        </else>
                                    </if>
                                </target>
                            </configuration>
                        </execution>
                        <execution>
                            <id>cobertura-copyResultSerFileAndSources</id>
                            <phase>verify</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <target>
                                    <taskdef resource="tasks.properties"/>
                                    <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>

                                    <echo message=":::copyResultSerFileAndSources -beforeIf"/>
                                    <if>
                                        <available file="${basedir}/cobertura.ser"/>
                                        <then>
                                            <echo message="move1"/>
                                            <move file="${basedir}/cobertura.ser" tofile="${cobertura.complete.ser.file}"/>
                                            <mkdir dir="${cobertura.working.dir}/source"/>
                                            <if>
                                                <available file="${basedir}/src/main/java"/>
                                                <then>
                                                    <copy todir="${cobertura.working.dir}/source">
                                                        <fileset dir="src/main/java">
                                                            <include name="**/*.java"/>
                                                        </fileset>
                                                    </copy>
                                                </then>
                                            </if>
                                            <echo message="runreport"/>
                                            <cobertura-report datafile="${cobertura.complete.ser.file}" format="${cobertura.format}" destdir="${cobertura.working.dir}/report">
                                                <fileset dir="${cobertura.working.dir}/source"/>
                                            </cobertura-report>
                                        </then>
                                    </if>
                                </target>
                            </configuration>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>net.sourceforge.cobertura</groupId>
                            <artifactId>cobertura</artifactId>
                            <version>1.9.4.1</version>
                        </dependency>
                        <dependency>
                            <groupId>ant-contrib</groupId>
                            <artifactId>ant-contrib</artifactId>
                            <version>20020829</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>net.sourceforge.cobertura</groupId>
                <artifactId>cobertura</artifactId>
                <version>1.9.4.1</version>
            </dependency>
        </dependencies>
    </profile>
    </profiles>

Ответ 6

Thomas Sundberg предлагает интересное решение, в котором контрольно-измерительные и тестовые отчеты выполняются с помощью ant, но все управление тестированием и зависимостью через mvn.

Проверить здесь: thomassundberg wordpress

Это означает, что вы должны выполнить команды ниже на родительском уровне в следующем порядке:

mvn clean compile
ant instrument
mvn test
ant report

Интеграция этих шагов в sonar описана Мартином Стелингей.

test-coverage-in-multi-module-projects