Skip to content

Commit 5a7cfe7

Browse files
gpascucciclaude
andcommitted
test(reporting): unit-test ReportPrecompiler to clear the Sonar coverage gate
#320's backend Sonar gate failed on new_coverage (12.1% < 80%): the new ReportPrecompiler is a build-time main() and reporting is otherwise covered only by Oracle ITs, which don't run in the CI unit-coverage job. Add ReportPrecompilerTest (a plain unit test — the CI test JVM is a JDK, so javac is present, exactly where the precompile runs): - compiles a real shipped .jrxml to a sibling .jasper, source left in place; - no-args -> IllegalArgumentException; - empty dir -> IllegalStateException (the fail-fast the reviewers asked for); - missing dir -> throws (no silent no-op). reporting/ isn't in the jacoco/sonar excludes, so this coverage registers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 5d143bb commit 5a7cfe7

1 file changed

Lines changed: 60 additions & 0 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package ca.bc.gov.nrs.ilcr.reporting;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
import static org.junit.jupiter.api.Assertions.assertTrue;
6+
7+
import java.io.InputStream;
8+
import java.nio.file.Files;
9+
import java.nio.file.Path;
10+
import java.nio.file.StandardCopyOption;
11+
import org.junit.jupiter.api.Test;
12+
import org.junit.jupiter.api.io.TempDir;
13+
14+
/**
15+
* Unit test for the BUILD-TIME report precompiler. Runs on the test JVM (a JDK, so {@code javac} is
16+
* present, unlike the JRE runtime container), which is exactly where the precompile is meant to
17+
* run. Pins the fail-fast contract: a build that compiles zero templates must fail rather than ship
18+
* an app with no {@code .jasper} to load (PR #320 review, SScholefield/Rylan #3).
19+
*/
20+
class ReportPrecompilerTest {
21+
22+
@Test
23+
void compilesJrxmlToSiblingJasper(@TempDir Path dir) throws Exception {
24+
// A real shipped template — the same ones the process-classes precompile handles.
25+
Path jrxml = dir.resolve("schedule5.jrxml");
26+
try (InputStream in = getClass().getResourceAsStream("/reports/schedule5.jrxml")) {
27+
Files.copy(in, jrxml, StandardCopyOption.REPLACE_EXISTING);
28+
}
29+
30+
ReportPrecompiler.main(new String[] {dir.toString()});
31+
32+
Path jasper = dir.resolve("schedule5.jasper");
33+
assertTrue(Files.exists(jasper), "expected a sibling .jasper to be produced");
34+
assertTrue(Files.size(jasper) > 0, "expected the compiled .jasper to have content");
35+
// The .jrxml source is left in place (only the extension is swapped, not replaced).
36+
assertTrue(Files.exists(jrxml), "the .jrxml source should remain");
37+
}
38+
39+
@Test
40+
void failsWhenNoArguments() {
41+
assertThrows(IllegalArgumentException.class, () -> ReportPrecompiler.main(new String[] {}));
42+
}
43+
44+
@Test
45+
void failsWhenDirectoryHasNoTemplates(@TempDir Path emptyDir) {
46+
// A green build that compiled nothing would surface only as a runtime 500 in the JRE container
47+
// (the exact bug the precompile fixes), so an empty compile set must fail the build.
48+
String[] args = {emptyDir.toString()};
49+
IllegalStateException ex =
50+
assertThrows(IllegalStateException.class, () -> ReportPrecompiler.main(args));
51+
assertTrue(ex.getMessage().contains("*.jrxml"), "message should name the missing templates");
52+
}
53+
54+
@Test
55+
void requiresAnExistingDirectory(@TempDir Path dir) {
56+
// A missing reports directory is a hard build error (fail-fast), not a silent no-op.
57+
Path missing = dir.resolve("does-not-exist");
58+
assertThrows(Exception.class, () -> ReportPrecompiler.main(new String[] {missing.toString()}));
59+
}
60+
}

0 commit comments

Comments
 (0)