Jacoco generate coverage report for only a single test class

11,172

JaCoCo does not execute your tests, it simply records information about what was executed. So execution of a tests, including case of a single test, is entirely depends on a tool that you use to execute tests, which unfortunately not mentioned in your question.

If you use Maven as a build tool, then execution of tests is usually done and controlled by maven-surefire-plugin, which has option test to run individual test. Here is example:

src/main/java/Example.java:

public class Example {
  public void doSomething(int p) {
    if (p == 1) {
      a();
    } else {
      b();
    }
  }

  private void a() {
    System.out.println("a");
  }

  private void b() {
    System.out.println("b");
  }
}

src/test/java/ExampleTest.java:

import org.junit.Test;

public class ExampleTest {
  @Test
  public void test1() {
    new Example().doSomething(1);
  }

  @Test
  public void test2() {
    new Example().doSomething(2);
  }
}

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>example</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.20.1</version>
      </plugin>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.7.9</version>
        <executions>
          <execution>
            <id>default-prepare-agent</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
          </execution>
          <execution>
            <id>default-report</id>
            <goals>
              <goal>report</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

</project>

Execution of mvn clean verify -Dtest=ExampleTest#test1 will produce following report in directory target/site/jacoco:

coverage of test1

and execution of mvn clean verify -Dtest=ExampleTest#test2 will produce:

coverage of test2

which show coverage of test1 and test2 respectively.

For comparison - execution of all tests by mvn clean verify produces:

coverage of all tests

Note about usage of clean: File target/jacoco.exec contains execution information and used for generation of report ( see agent option destfile and corresponding parameter of jacoco-maven-plugin ). By default JaCoCo agent appends to this files ( see agent option append and corresponding parameter of jacoco-maven-plugin ), so that clean is used in this example to prevent accumulation of data in this file about previous executions.

If you use Gradle, then it also has similar ability - given same sources and build.gradle:

apply plugin: 'java'
apply plugin: 'jacoco'

repositories {
  mavenCentral()
}

dependencies {
  testCompile 'junit:junit:4.12'
}

execution of gradle clean test --tests ExampleTest.test1 jacocoTestReport will produce report containing coverage of test1, which is the same as in case of Maven.

Similarly to example for Maven, clean is used in this example to prevent accumulation of data about previous executions in file build/jacoco/test.exec - see append property of JaCoCo Gradle Plugin.

If you use Eclipse IDE, then there is EclEmma Eclipse plugin that integrates JaCoCo in Eclipse IDE and included by default in "Eclipse IDE for Java Developers" starting from Oxygen (4.7) version. With it you can also get coverage of single test in Eclipse IDE - in editor right mouse click on a test name to get context menu and select "Coverage As -> JUnit Test".

Share:
11,172
Bhargav
Author by

Bhargav

First! Checkout my libs! https://github.com/bhargavms/PodSLider https://github.com/bhargavms/DotLoader I love coding and I am not biased towards any particular language. Currently dabbling in android application development. Developing android applications is more of a write once debug everywhere experience right now. I am also an avid mmorpg fan. Have played world of warcraft and other similar mmos before programming captured my heart, now I just look at other people playing (on twitch.tv) from time to time just to bring in some nostalgia.

Updated on July 25, 2022

Comments

  • Bhargav
    Bhargav almost 2 years

    So let us say I have a test

    @Test
    public void testA(){
        new A().doSomthing();
    }
    

    And let us say it covers a method doSomething(), Now in my project, I have 10million tests and this test is just one of those. A small test doesn't do much.

    Now let us say my doSomething method looks like this:-

    public void doSomething() {
        if (var1)
            killMylSelf();
        else if (var2)
            killMyMother();
        else
            killMySelfAndMyMother();
    }
    

    So as you can see there are a lot of branches in the method, that consequently call other methods that have even more branches. When I run testA I want to see which branches I have missed in the code that got executed, how can I achieve this WITHOUT HAVING TO RUN ALL THE UNIT TESTS AND ONLY THE TEST THAT I CARE ABOUT,

    Remember these magical words when you answer the question WITHOUT HAVING TO RUN ALL THE UNIT TESTS AND ONLY THE TEST THAT I CARE ABOUT

  • Bhargav
    Bhargav over 6 years
    Do I need to say gradle after mentioning android studio? Anyway a very comprehensive answer I like it, if the number of tests that run after executing your command exceeds one, I would be sourly disappointed :(, will give this a shot and let ou know in 12hours! Thanks for the help
  • Godin
    Godin over 6 years
    @Bhargav search in browser on this page tells me that "android" was first time mentioned in your comment, but not in a question ;) Android is a bit different beast and I'm not an Android expert, but according to developer.android.com/studio/test/command-line.html "Android Plugin for Gradle" supports the same option "--tests" as "Gralde Java Plugin" that was mentioned in my answer for execution of single test.
  • Godin
    Godin over 6 years
    @Bhargav And according to developer.android.com/studio/test/index.html#view_test_cover‌​age running a single test with coverage in Android Studio is possible and is not different than running test with coverage in IntelliJ IDEA.
  • Bhargav
    Bhargav over 6 years
    the IDE doesnt report branch coverage sadly.
  • Bhargav
    Bhargav over 6 years
    Sadly running jacocoTestReport triggers its dependsOn which executes all the Unit tests in the module :(
  • Godin
    Godin over 6 years
    @Bhargav according to docs.gradle.org/current/userguide/… jacocoTestReport has no dependensOn. And again your initial question lacks clarity, because lacks concrete Minimal, Complete, and Verifiable example. While I'm pretty sure that there are many ways to bypass dependsOn eg. with new task without dependsOn, I'll stop suggestions, because sorry but in absence of concrete example I think that attempts to guess all aspects of your particular configuration are counterproductive and a kind of waste of time.
  • Jack
    Jack about 2 years
    Thanks for detailed explanations. I am using Maven and applied all the settings you mentioned, but unfortunately mvn clean verify -Dtest=MyTestClassName#MyTestMethodName does not create any test report or site folder in the target directory. There is no error and build successfully completed and the other folders are created in that directory. Any idea?