0
votes

I'm trying to integrate codecoverage with jacoco in my junit tests that are launched by an ant task. The fact that jacoco forces me to fork my junit it's given me some problem, since my classpath is quite long and the fork crashes. I'm using manifestclasspath to add my classpath in a jar file an send my new jar as an argument to the VM but it's not working. My tests run but they all return a ClassNotFoundException. Here's a portin of how I've configured my ant process.

<path refid="bin.classpath"/>

bin.classpath contains all the paths that I need to put in my .jar file.

<target name="run-unit-tests" depends="init" description="Runs all the unit tests">
  <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
    <classpath path="jacocoant.jar" />
  </taskdef>

  <manifestclasspath property="binjar" jarfile="binManifest.jar">
    <classpath refid="bin.classpath" />
  </manifestclasspath>

  <jar destfile="manifestJars/binManifest.jar">
    <manifest>
      <attribute name="Class-Path" value="${binjar}" />
    </manifest>
  </jar>

  <jacoco:coverage destfile="results/jacoco.exec" xmlns:jacoco="antlib:org.jacoco.ant">
    <junit fork="true" reloading="false" showoutput="true">
      <classpath>
        <pathelement path="${projects.dir}/AntProject/manifestJars/binManifest.jar" />
      </classpath>

      <batchtest todir="${test.data.dir}" fork="true">
        <fileset dir="${projects.dir}/ProjectFolder1/src" />
        <fileset dir="${projects.dir}/ProjectFolder2/src" />
      </batchtest>
    </junit>
  </jacoco:coverage>
</target>

If I look at console log when running the ant-task I can see how my new .jar file is being send:

-classpath''C:\Users\XXX\Project\AntProject\manifestJars\binManifest.jar;

If I open the binManifest.jar created I find a MANIFEST.MF file with all my paths inside Class-Path property with the format: ../../Class1/bin ../../Class2/bin ../../ClassN/bin. But for some reason all my tests fail because my classes are not found. What am I missing? Thanks.

1
Since paths are relative (../../Class1/bin) wield guess is that maybe working directory is incorrect. - Godin
Thanks for your answer @Godin . I've thought so too, but I've tried changing my manifest.mf content to put absolute paths or changing my .jar file to root folder. For the first case the tests were crashing with the same error, and for the second case the relative path being shown was exactly the same - KKrusti

1 Answers

1
votes

Let's start without JaCoCo - below is a complete and verifiable example that uses junit fork="true" and manifestclasspath.

main/Example.java:

class Example {
  public static void sayHello() {
    System.out.println();
  }
}

test/ExampleTest.java:

public class ExampleTest {
  @org.junit.Test
  public void test() {
    Example.sayHello();
  }
}

build.xml:

<project xmlns:jacoco="antlib:org.jacoco.ant" default="build">
  <target name="build">
    <delete dir="bin" />
    <mkdir dir="bin/main-classes" />
    <mkdir dir="bin/test-classes" />

    <javac target="1.5" debug="true" destdir="bin/main-classes">
      <src path="main" />
    </javac>

    <javac target="1.5" debug="true" destdir="bin/test-classes">
      <src path="test" />
      <classpath>
        <pathelement path="bin/main-classes"/>
        <pathelement path="lib/junit-4.12.jar"/>
        <!-- otherwise "java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing" -->
        <pathelement path="lib/hamcrest-core-1.3.jar"/>
      </classpath>
    </javac>

    <manifestclasspath property="binjar" jarfile="bin/manifest.jar">
      <classpath>
        <pathelement path="bin/main-classes"/>
        <pathelement path="bin/test-classes"/>

        <pathelement path="lib/junit-4.12.jar"/>
        <!-- otherwise "java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing" -->
        <pathelement path="lib/hamcrest-core-1.3.jar"/>
      </classpath>
    </manifestclasspath>

    <jar destfile="bin/manifest.jar">
      <manifest>
        <attribute name="Class-Path" value="${binjar}" />
      </manifest>
    </jar>

    <junit fork="true" showoutput="true">
      <formatter type="brief" usefile="false" />
      <classpath>
        <pathelement path="bin/manifest.jar" />
      </classpath>
      <batchtest>
        <fileset dir="test" includes="**/*Test.java" />
      </batchtest>
    </junit>
  </target>
</project>

Note presence of lib/hamcrest-core-1.3.jar in addition to junit-4.12.jar as per requirements of Junit - see https://github.com/junit-team/junit4/wiki/Download-and-Install

Let's confirm that it works without exceptions by execution of ant.

After that addition of JaCoCo by addition of

<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
  <classpath path="jacocoant.jar" />
</taskdef>

to the beginning,

<jacoco:coverage destfile="bin/jacoco.exec" xmlns:jacoco="antlib:org.jacoco.ant">
...
</jacoco:coverage>

around junit and finally

<jacoco:report>
  <executiondata>
    <file file="bin/jacoco.exec"/>
  </executiondata>
  <structure name="JaCoCo Ant Example">
    <classfiles>
      <fileset dir="bin/main-classes"/>
    </classfiles>
    <sourcefiles encoding="UTF-8">
      <fileset dir="main"/>
    </sourcefiles>
  </structure>
  <html destdir="bin/report"/>
</jacoco:report>

to the end is not a big deal. And execution of ant will produce report in directory bin/report.