Search code examples
androidpluginsmavenemma

How do I exclude classes from being instrumented by the maven-emma plugin?


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.


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>