2

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.

android.weasel
  • 3,343
  • 1
  • 30
  • 41
  • Could you tell a little bit more about your project structure, do you create your own library project, do you add svg android to both your library and main project dependencies? – yorkw Mar 02 '12 at 22:52
  • 1
    It turns out the 'already instrumented' error arose from having the 'executions' element schedule a non-default execution of the instrumentation goal in addition to the default one. Taking out the explicit phase would have configured the default one. I was cobbling this together from several examples, one of which was trying to add coverage in a particular way inapplicable to my situation. – android.weasel Mar 04 '12 at 08:09

3 Answers3

5

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>
android.weasel
  • 3,343
  • 1
  • 30
  • 41
  • please do and if you can show final config would be nice because above description did really confused me ;) – peter_budo Mar 04 '12 at 15:53
  • Updated, sorry. Comment to say if the config above satisfies you, I'll consider myself to've won your bounty and tick my answer. – android.weasel Mar 07 '12 at 10:57
  • Also, I didn't update because I got distracted trying to work out how the inclusions and exclusions play with each other because... although exclusions work, it kinda looks like mixing inclusions with exclusions (e.g. allow all, exclude com.foo.*, but allow com.foo.interesting.* despite the exclusion - +*-com.foo.*+com.foo.interesting.*) doesn't work for me. – android.weasel Mar 07 '12 at 11:02
  • Sorry couldn't get your setup working with my one. I tweaked android maven plugin emma wiki to my needs now http://code.google.com/p/maven-android-plugin/wiki/EmmaMaven – peter_budo Mar 09 '12 at 11:50
2

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.!

Community
  • 1
  • 1
  • 1
    But the question was about Emma, not Cobertura? Which said, it's probably only Android keeping Emma alive, since it seems to be well out of maintenance. – android.weasel Mar 04 '12 at 08:16
0

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

Aditya Bhuyan
  • 328
  • 6
  • 10