ReviseAlgo Logo

Testing in Java

Code Coverage with JaCoCo

Understand instruction, branch, and line coverage using the JaCoCo agent parser.

Interview: Tests understanding of execution metrics. Expect discussions on branch coverage vs line coverage, and how code coverage can mislead teams.

Last Updated: June 13, 2026 8 min read

JaCoCo (Java Code Coverage) is a lightweight library that tracks code paths executed during testing. It operates as a JVM agent that injects tracking instructions directly into compiled bytecode at runtime.

Instruction

Measures the smallest units of compiled Java bytecode instructions executed by test runs.

Line

Checks if a given line of Java source code was touched by tests. Can be misleading.

Branch

Verifies if both true and false paths of decision blocks (if, switch) are hit.

Branch vs Line Coverage

Line coverage tracks only if a line of code is entered. It can easily mask missing logical tests. Consider a single line conditional:

if (isActive && isVerified) { doTask(); }

If a test executes this line with isActive = true and isVerified = true, the line is fully covered. However, you have not tested what happens if isActive is false. Branch Coverage ensures all combinations of conditional paths are exercised.

Code Walkthrough

Here is a method requiring multiple test branches to achieve 100% branch coverage.

public class CoverageDemo {

public int calculateDiscount(int price, boolean premiumMember) { if (premiumMember && price > 100) { return (int) (price * 0.8); } return price; } }

Interview-Relevant Information

Q: Does 100% code coverage mean my code is bug-free?
Answer: Absolutely not. Code coverage only measures which lines were executed. It does not evaluate if you assert the correct output, handle unexpected inputs, or manage memory leaks and thread safety issues. Coverage is a metric of untested code, not tested correctness.

Q: How does JaCoCo gather coverage metrics without source files?
Answer: JaCoCo instruments bytecode class files by injecting probes (boolean tracking flags) dynamically when the JVM loads classes, or statically during the compile build phase. When tests run, executed probes set flags to true, and JaCoCo dumps this metadata to a binary report file (jacoco.exec) for analysis.

Quick Checklist

Can you explain why branch coverage is safer than line coverage? Do you know how bytecode instrumentation collects probe data? If yes, you understand coverage.

Use Cases

Configuring build pipeline gates to reject commits that drop branch coverage below 80%.

Identifying dead code blocks or unused functions that tests never touch.

Common Mistakes

Aiming for 100% line coverage at the cost of assertion quality (e.g. writing assertionless tests just to run lines).

Counting auto-generated boilerplate (like getters/setters) towards code coverage, artificially inflating metrics. Exclude them using jacoco configurations.