IT Coverage for Modular Spring Apps | Generated by AI

Home 2025.09

Overall Assessment of Your Setup

Your current configuration is solid for a small multi-module project like this, especially since you’ve already got the core flow working: attaching the JaCoCo agent to Jetty, running external Python integration tests via the Exec Plugin, and generating a report in the PlaygroundWeb module. This captures runtime coverage from API endpoints tested by Python’s unittest, which is exactly what you need for integration test (IT) coverage in a Spring web app.

Key strengths:

Challenges you’ve identified:

Your fallback to per-module reports is pragmatic, but we can optimize for coverage inclusion without duplication.

Focus on generating a single, comprehensive IT coverage report in the module that runs the app (PlaygroundWeb here), while including coverage data for dependent modules like PlaygroundUtils. This avoids running tests multiple times and leverages the fact that all code executes in one JVM.

Why this over aggregation?

Step-by-Step Implementation for Your 2-Module Project

Start small: Apply this to your current setup (1 app module + 1 lib). Test it, then expand.

  1. Keep IT Execution in PlaygroundWeb Only:
    • No changes needed here. Jetty starts the WAR (which embeds PlaygroundUtils), Python tests hit endpoints, coverage is captured in ${project.build.directory}/jacoco.it.exec.
    • Confirm utils code is exercised: If your Python tests call endpoints that use PlaygroundUtils classes (e.g., SystemUtils), their coverage will be in the .exec file.
  2. Enhance the JaCoCo Report in PlaygroundWeb to Include PlaygroundUtils:
    • Use JaCoCo’s <additionalClassesDirectories> and <additionalSourceDirectories> in the report goal. This tells JaCoCo to scan classes/sources from PlaygroundUtils against the same .exec file.
    • Update PlaygroundWeb’s POM (in the jacoco-maven-plugin configuration):

      <plugin>
          <groupId>org.jacoco</groupId>
          <artifactId>jacoco-maven-plugin</artifactId>
          <executions>
              <!-- Existing prepare-agent -->
              <execution>
                  <id>prepare-agent</id>
                  <goals>
                      <goal>prepare-agent</goal>
                  </goals>
              </execution>
              <!-- Enhanced report: Include utils module -->
              <execution>
                  <id>report-it</id>
                  <phase>verify</phase>
                  <goals>
                      <goal>report</goal>
                  </goals>
                  <configuration>
                      <dataFile>${jacoco.it.exec}</dataFile>
                      <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
                      <!-- Add these to include PlaygroundUtils coverage -->
                      <additionalClassesDirectories>
                          <directory>${project.parent.basedir}/PlaygroundUtils/target/classes</directory>
                      </additionalClassesDirectories>
                      <additionalSourceDirectories>
                          <directory>${project.parent.basedir}/PlaygroundUtils/src/main/java</directory>
                      </additionalSourceDirectories>
                  </configuration>
              </execution>
          </executions>
      </plugin>
      
    • This generates one report (in PlaygroundWeb/target/site/jacoco-it) covering both modules. You’ll see breakdowns by package/class, including org.lzw from utils.
  3. Disable/Remove JaCoCo from PlaygroundUtils:
    • Since it has no IT of its own, remove any JaCoCo config/properties (e.g., <jacoco.it.exec>, <it.report.skip>). It doesn’t need to generate its own report—coverage is handled upstream.
    • If you have unit tests in utils, keep a separate prepare-agent + report for unit coverage (default jacoco.exec), but isolate it from IT.
  4. Build and Verify:
    • Run mvn clean verify from the parent.
    • Jetty/Python run only once (in PlaygroundWeb).
    • Check PlaygroundWeb/target/site/jacoco-it/index.html: It should show coverage for both modules’ classes.
    • If utils coverage is 0%, ensure your Python tests exercise those classes (e.g., add a test that triggers SystemUtils via an endpoint).
  5. Optional: Enforce Coverage Thresholds:
    • Add a check execution in PlaygroundWeb’s JaCoCo plugin to fail the build if coverage drops below a threshold (e.g., 70% line coverage overall).
      <execution>
          <id>check-it</id>
          <goals>
              <goal>check</goal>
          </goals>
          <configuration>
              <dataFile>${jacoco.it.exec}</dataFile>
              <rules>
                  <rule>
                      <element>BUNDLE</element>
                      <limits>
                          <limit>
                              <counter>LINE</counter>
                              <value>COVEREDRATIO</value>
                              <minimum>0.70</minimum>
                          </limit>
                      </limits>
                  </rule>
              </rules>
          </configuration>
      </execution>
      

Scaling to a Larger Project (e.g., 10 Modules)

For 10+ modules (e.g., multiple libs + 1-2 app/WAR modules), extend the above to avoid complexity:

This strategy minimizes runs (one Jetty/Python per app), handles JaCoCo’s dependencies cleanly, and scales without explosion. If you share more details (e.g., how utils is used in endpoints), I can refine the POM snippets further.


Back Donate