Add JaCoCo branch coverage gate (80% minimum) to Maven build #120

Closed
opened 2026-03-27 18:35:46 +01:00 by marcel · 2 comments
Owner

Problem

The backend build has no coverage measurement. There is no JaCoCo plugin configured, no coverage report generated, and the CI pipeline never reports a coverage number. The 80% branch coverage floor we aim for is completely unenforced — we don't even know what the current coverage is.

Why This Matters

Line coverage is a vanity metric. Branch coverage tells you whether your tests actually exercise decision points — the if/else, the switch, the Optional.orElseThrow. Without measuring it, we have no signal when a new service method ships with zero test coverage. A missed branch on an error path is exactly where production bugs hide.

What Needs To Be Done

  1. Add JaCoCo Maven plugin to pom.xml:
    <plugin>
      <groupId>org.jacoco</groupId>
      <artifactId>jacoco-maven-plugin</artifactId>
      <executions>
        <execution>
          <id>prepare-agent</id>
          <goals><goal>prepare-agent</goal></goals>
        </execution>
        <execution>
          <id>report</id>
          <phase>verify</phase>
          <goals><goal>report</goal></goals>
        </execution>
        <execution>
          <id>check</id>
          <phase>verify</phase>
          <goals><goal>check</goal></goals>
          <configuration>
            <rules>
              <rule>
                <element>BUNDLE</element>
                <limits>
                  <limit>
                    <counter>BRANCH</counter>
                    <value>COVEREDRATIO</value>
                    <minimum>0.80</minimum>
                  </limit>
                </limits>
              </rule>
            </rules>
          </configuration>
        </execution>
      </executions>
    </plugin>
    
  2. Run ./mvnw verify to get the current coverage baseline
  3. Exclude generated code and config classes from coverage measurement (DTOs, @Configuration classes)
  4. Upload the JaCoCo XML report as a CI artifact

Acceptance Criteria

  • ./mvnw verify fails if branch coverage drops below 80%
  • Coverage report uploaded as artifact in CI
  • Current coverage is ≥ 80% (or a plan exists to close the gap)
## Problem The backend build has no coverage measurement. There is no JaCoCo plugin configured, no coverage report generated, and the CI pipeline never reports a coverage number. The 80% branch coverage floor we aim for is completely unenforced — we don't even know what the current coverage is. ## Why This Matters Line coverage is a vanity metric. Branch coverage tells you whether your tests actually exercise decision points — the `if/else`, the `switch`, the `Optional.orElseThrow`. Without measuring it, we have no signal when a new service method ships with zero test coverage. A missed branch on an error path is exactly where production bugs hide. ## What Needs To Be Done 1. Add JaCoCo Maven plugin to `pom.xml`: ```xml <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <executions> <execution> <id>prepare-agent</id> <goals><goal>prepare-agent</goal></goals> </execution> <execution> <id>report</id> <phase>verify</phase> <goals><goal>report</goal></goals> </execution> <execution> <id>check</id> <phase>verify</phase> <goals><goal>check</goal></goals> <configuration> <rules> <rule> <element>BUNDLE</element> <limits> <limit> <counter>BRANCH</counter> <value>COVEREDRATIO</value> <minimum>0.80</minimum> </limit> </limits> </rule> </rules> </configuration> </execution> </executions> </plugin> ``` 2. Run `./mvnw verify` to get the current coverage baseline 3. Exclude generated code and config classes from coverage measurement (DTOs, `@Configuration` classes) 4. Upload the JaCoCo XML report as a CI artifact ## Acceptance Criteria - [ ] `./mvnw verify` fails if branch coverage drops below 80% - [ ] Coverage report uploaded as artifact in CI - [ ] Current coverage is ≥ 80% (or a plan exists to close the gap)
marcel added the test label 2026-03-27 18:45:07 +01:00
Author
Owner

Architect review (@mkeller): ⚠️ The JaCoCo config is correct, but the sequencing matters.

Do #119 (Testcontainers + real PostgreSQL) before adding this gate. If you add an 80% branch coverage floor today against the current mock-heavy test suite, you will either discover the gate immediately fails and disable it in frustration, or you'll find coverage appears artificially high because barely-touched service methods don't contribute meaningful branches. Neither gives useful signal.

Right sequence:

  1. Complete #119 — write real repository and service tests against PostgreSQL
  2. Run ./mvnw verify to get the actual measured baseline
  3. Set the gate at the current baseline (not aspirationally at 80%)
  4. Ratchet it upward deliberately over time

The acceptance criterion "Current coverage is ≥ 80% (or a plan exists to close the gap)" is a bit circular — you need to measure before you can know whether a plan is needed.

**Architect review (@mkeller):** ⚠️ The JaCoCo config is correct, but the sequencing matters. Do #119 (Testcontainers + real PostgreSQL) before adding this gate. If you add an 80% branch coverage floor today against the current mock-heavy test suite, you will either discover the gate immediately fails and disable it in frustration, or you'll find coverage appears artificially high because barely-touched service methods don't contribute meaningful branches. Neither gives useful signal. Right sequence: 1. Complete #119 — write real repository and service tests against PostgreSQL 2. Run `./mvnw verify` to get the actual measured baseline 3. Set the gate at the current baseline (not aspirationally at 80%) 4. Ratchet it upward deliberately over time The acceptance criterion "Current coverage is ≥ 80% (or a plan exists to close the gap)" is a bit circular — you need to measure before you can know whether a plan is needed.
Author
Owner

Baseline measured: 46.8% branch coverage (265/566 branches covered, excluding DTOs, config classes, model entities, and ErrorCode enum).

Initial gate set at 42% (baseline − 5%) to prevent regression without blocking CI.

Gap to target: 46.8% → 80% = 33.2 percentage points. The main coverage gaps are service error paths (DomainException branches in DocumentService, PersonService, UserService) and the security/permission layer. Each new service test that covers an error path will close this gap.

**Baseline measured: 46.8% branch coverage** (265/566 branches covered, excluding DTOs, config classes, model entities, and ErrorCode enum). Initial gate set at **42%** (baseline − 5%) to prevent regression without blocking CI. Gap to target: 46.8% → 80% = **33.2 percentage points**. The main coverage gaps are service error paths (DomainException branches in DocumentService, PersonService, UserService) and the security/permission layer. Each new service test that covers an error path will close this gap.
Sign in to join this conversation.
No Label test
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#120