DEV Community

Taras Antoniuk
Taras Antoniuk

Posted on

JaCoCo for Java Developers: Measuring and Improving Code Coverage

Testing and Code Coverage Guide

Why Testing Matters

Testing is crucial for software quality. It helps us:

  • Catch bugs early before they reach production
  • Refactor code with confidence
  • Document how code should behave
  • Maintain code quality over time

But testing alone isn't enough. We also need to know how much of our code is actually tested. That's where code coverage comes in.


What is Code Coverage?

Code coverage measures which parts of your code are executed during tests. It shows:

  • Line coverage: Percentage of code lines executed
  • Branch coverage: Percentage of decision branches (if/else) tested

Example: If you have 100 lines of code and tests execute 80 of them, you have 80% line coverage.


Our Testing Approach

We use:

  • JUnit 5 for writing tests
  • Testcontainers for integration tests with real database
  • JaCoCo for measuring code coverage

Coverage standards:

  • 80% line coverage minimum
  • 75% branch coverage minimum

JaCoCo in Action: Real Example

Let's see how we implemented code coverage in this project.

Live Example: You can see the complete implementation in my repository:

https://github.com/TarasAntoniuk/finance-core

Step 1: Add JaCoCo to Maven

In pom.xml, we added the JaCoCo plugin:

<properties>
    <jacoco.version>0.8.12</jacoco.version>
    <jacoco.line.coverage>0.80</jacoco.line.coverage>
    <jacoco.branch.coverage>0.75</jacoco.branch.coverage>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco.version}</version>
            <executions>
                <execution>
                    <id>prepare-agent</id>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                </execution>
                <execution>
                    <id>report</id>
                    <phase>test</phase>
                    <goals>
                        <goal>report</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
Enter fullscreen mode Exit fullscreen mode

Step 2: Exclude Non-Business Code

Not all code needs testing. We excluded:

  • Configuration classes (just Spring setup)
  • DTOs and entities (simple data holders)
  • MapStruct generated mappers
  • Exception classes
<configuration>
    <excludes>
        <exclude>**/*Config.class</exclude>
        <exclude>**/dto/**</exclude>
        <exclude>**/entity/**</exclude>
        <exclude>**/mapper/**</exclude>
        <exclude>**/exception/**</exclude>
    </excludes>
</configuration>
Enter fullscreen mode Exit fullscreen mode

Step 3: Run Tests and View Coverage

# Run tests with coverage
mvn clean test

# Open HTML report
open target/site/jacoco/index.html
Enter fullscreen mode Exit fullscreen mode

The report shows:

  • Overall coverage percentage
  • Which classes are well-tested (green)
  • Which need more tests (red/yellow)
  • Line-by-line coverage details

Step 4: Add Coverage Badges to GitHub

We created a separate GitHub Actions workflow that:

  1. Runs tests on every push
  2. Generates coverage badges
  3. Commits badges to repository
  4. Displays them in README

Workflow (.github/workflows/test-coverage.yml):

- name: Run tests with coverage
  run: mvn clean test

- name: Generate JaCoCo Badge
  uses: cicirello/jacoco-badge-generator@v2
  with:
    badges-directory: .github/badges
Enter fullscreen mode Exit fullscreen mode

Result in README.md:

![Coverage](.github/badges/jacoco.svg)
![Branches](.github/badges/branches.svg)
Enter fullscreen mode Exit fullscreen mode

Now everyone can see test coverage at a glance! ๐Ÿ“Š

Step 5: Enforce Coverage in CI (Optional)

We can make the build fail if coverage drops below our standards:

<profile>
    <id>ci</id>
    <build>
        <plugins>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>check-coverage</id>
                        <goals>
                            <goal>check</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <rule>
                                    <limits>
                                        <limit>
                                            <counter>LINE</counter>
                                            <minimum>0.80</minimum>
                                        </limit>
                                    </limits>
                                </rule>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>
Enter fullscreen mode Exit fullscreen mode

Run with: mvn verify -P ci


Key Takeaways

  1. Test your business logic โ€” that's where bugs hide
  2. Measure coverage โ€” know what's tested and what isn't
  3. Don't chase 100% โ€” focus on meaningful tests, not numbers
  4. Automate โ€” let CI/CD run tests and report coverage
  5. Make it visible โ€” badges help track progress

Testing takes time upfront but saves much more time debugging production issues later.


Quick Commands Reference

# Run tests
mvn test

# View coverage report
open target/site/jacoco/index.html

# Run with coverage enforcement
mvn verify -P ci
Enter fullscreen mode Exit fullscreen mode

Resources:


Document Version: 0.0.2

Last Updated: November 2025

Top comments (0)