Question

I have some unit tests (although they're Android tests, I'm using Robolectric, so they're running on the JVM). They run happily without coverage.

I'm getting this error from emma-maven when I try it with coverage:

org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.codehaus.mojo:emma-maven-plugin:1.0-alpha-3:instrument (default-cli) on project android: Execution default-cli of goal org.codehaus.mojo:emma-maven-plugin:1.0-alpha-3:instrument failed: class [com.larvalabs.svgandroid.ParserHelper] appears to be instrumented already

The important bit is class .... appears to be instrumented already.

It's very hard to find proper documentation, but this is what I've cobbled together for the configuration from various sources:

<plugin>
    <!-- This doesn't work, see below for a working configuration -->
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>emma-maven-plugin</artifactId>
    <version>1.0-alpha-3</version>
    <inherited>true</inherited>                          
    <executions>
            <execution>
                    <phase>process-classes</phase>                               
                    <configuration>
                            <filters>
                                    <filter>-com.viewpagerindicator.*</filter>
                                    <filter>-com.actionbarsherlock.*</filter>
                                    <filter>-com.larvalabs.svgandroid.*</filter>
                            </filters>
                    </configuration>
                    <goals> 
                            <goal>instrument</goal>
                    </goals>
            </execution>
    </executions>
</plugin>

The trouble is, having excluded those packages it was complaining about (I thought the issue was that these are Android library-projects inadvertently ending up twice on some list of paths), it's now complaining about my own packages.


A colleague incorrectly suggested the <plugin> section above should go in <project><build><pluginManagement>.

It turns out that the <configuration> should be directly in <plugin> and the leftover <executions> bit should be removed, see answer.

Was it helpful?

Solution

I found a solution - embarrassingly simple.

Forget the pluginManagement stuff: that only 'worked' by making it ignore the filters for /this/ pom, but apply them to any child poms: http://maven.apache.org/pom.html#Plugin_Management

Just move the configuration element out of the executions block, and remove the executions block. http://maven.apache.org/guides/mini/guide-configuring-plugins.html#Generic_Configuration

With the configuration section immediately inside the plugin element, running with 'mvn -X emma:emma' showed the filters listed. Since each exclusion line changed the error I saw, I infer it was excluding. (I gather that to include, you add filters with + prefixes to override sections of foregoing - prefixes.)

<project>
 <build>
  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>emma-maven-plugin</artifactId>
    <version>1.0-alpha-3</version>
    <!-- inherited>true</inherited -->
    <configuration>
            <filters>
                    <filter>-com.viewpagerindicator.*</filter>
                    <filter>-com.actionbarsherlock.*</filter>
                    <filter>-com.larvalabs.svgandroid.*</filter>
            </filters>
            <!-- verbose>true</verbose -->
   </configuration>
  </plugin>

So far as the implied Android part of the question goes (which actually makes the filtering quite moot for me), because Android needs a separate APK to hold the tests and exercise the main application APK, you simply don't run Android integration tests from the same project: the android plugin wants you to make the integration test APK from a separate project - typically a sibling under the same parent pom file. There are example/sample projects in a zip hiding on the android plugin page - http://code.google.com/p/maven-android-plugin/wiki/Samples - within which you should search for 'coverage' and change it to:

<coverage>true</coverage>

to the configuration - a couple of the samples have it, but commented out. I got distracted so can't remember whether that worked, but it's clearly supposed to.

Since we didn't want to insert a directory level into our project's existing source control, we created directories called 'parent' and 'integration' as peers of the application's pom.xml, using 'parent' to hold the parent pom, and 'integration' for the integration tests, with this section to tell app/pom.xml to use app/parent/pom.xml:

<project>
    <parent>
            <groupId>our.group.id</groupId>
            <artifactId>base</artifactId>
            <relativePath>parent</relativePath>
            <version>3.9.0</version>
    </parent>

and this in app/integration/pom.xml:

<project>
  <parent>
    <groupId>our.group.id</groupId>
    <artifactId>base</artifactId>
    <relativePath>../parent</relativePath>
    <version>3.9.0</version>
  </parent>

OTHER TIPS

As far as I understand, the instrumented classes are only needed by cobertura for report generation. If you create them in target/classes, they will overwrite the original class files.

If you need the instrumented files in a jar as a result, you can configure the maven-jar-plugin to pick up the files from the target/generated-classes directory instead of or in addition to the files from the standard ${build.project.outputDirectory}.

Edit

Have a look at the maven-jar-plugin description. To only use target/generated-classes, the following addition to your POM should work - try it and modify it to your needs:

<project>
  ...
  <build>
    <plugins>
      ...
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.3</version> <!-- replace with correct version nbr! -->
        <configuration>
          <includes>
            <include>${project.build.directory}/generated-classes/**/*.class</include>
          </includes>
          <excludes>
            <exclude>${project.build.directory}/classes/**/*.class</include>
          </excludes>

        </configuration>
      </plugin>
      ...
    </plugins>
  </build>
  ...
</project>

${project.build.directory} points to your target folder, ${project.build.ouputDirectory} to target/classes. I do not know if you can simply set ${project.build.ouputDirectory} to a new value - have a look at the this chapter of the maven book, maybe you find some hints

Refer :

Alternativly or additionally you can use maven to copy the files from target/generated-classes to target/classes after coberture:instrument has finished. This question has one answer with an example POM (fragment), you just have to identify the correct phase (process-resources is definitely too early for your case)

And Also Refer this

Hope it Helps.!

Please use mode="overwrite". It would work fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top