TestReport Storage¶
FHIR Frog provides multiple options for storing TestReports.
Storage Backends¶
File System¶
Store reports as JSON or XML files:
FileSystemReportStorage storage = new FileSystemReportStorage(
Path.of("target/fhir-reports")
);
storage.store(testReport, "json");
FHIR Server¶
Upload reports to a FHIR server:
IGenericClient client = FhirContext.forR4()
.newRestfulGenericClient("http://localhost:8080/fhir");
ServerReportStorage storage = new ServerReportStorage(client);
storage.store(testReport);
Composite¶
Store in multiple locations:
CompositeReportStorage storage = new CompositeReportStorage(
new FileSystemReportStorage(Path.of("reports")),
new ServerReportStorage(fhirClient)
);
storage.store(testReport);
Configuration¶
JUnit¶
@ExtendWith(FhirFrogExtension.class)
@GenerateTestReport(
format = "json",
outputDir = "target/reports",
uploadToServer = true,
serverUrl = "http://localhost:8080/fhir"
)
class Tests {}
Maven¶
<configuration>
<reportDir>target/fhir-reports</reportDir>
<reportFormat>both</reportFormat>
<uploadReports>true</uploadReports>
<reportServerUrl>http://localhost:8080/fhir</reportServerUrl>
</configuration>
CLI¶
java -jar fhir-frog-cli.jar \
-t test.json \
-s http://localhost:8080/fhir \
-r ./reports \
-f json \
--upload-reports
File Organization¶
By Date¶
reports/
2026-03-11/
patient-crud-123456.json
practitioner-crud-123457.json
2026-03-12/
patient-crud-234567.json
By Test¶
reports/
patient-crud/
2026-03-11-123456.json
2026-03-11-234567.json
practitioner-crud/
2026-03-11-123456.json
Implementation¶
public class DateBasedStorage implements ReportStorage {
private final Path baseDir;
@Override
public void store(TestReport report, String format) {
LocalDate date = LocalDate.now();
Path dateDir = baseDir.resolve(date.toString());
Files.createDirectories(dateDir);
String filename = report.getId() + "." + format;
Path reportPath = dateDir.resolve(filename);
// Write report
}
}
Server Storage¶
Create Report¶
IGenericClient client = fhirContext.newRestfulGenericClient(serverUrl);
MethodOutcome outcome = client.create()
.resource(testReport)
.execute();
String reportId = outcome.getId().getIdPart();
Search Reports¶
Bundle results = client.search()
.forResource(TestReport.class)
.where(TestReport.TEST_SCRIPT.hasId("patient-crud"))
.returnBundle(Bundle.class)
.execute();
Update Report¶
Retention Policies¶
Delete Old Reports¶
public void cleanupOldReports(Path reportDir, int daysToKeep) {
LocalDate cutoff = LocalDate.now().minusDays(daysToKeep);
Files.walk(reportDir)
.filter(Files::isRegularFile)
.filter(p -> isOlderThan(p, cutoff))
.forEach(this::deleteQuietly);
}
Archive Reports¶
public void archiveOldReports(Path reportDir, Path archiveDir) {
LocalDate cutoff = LocalDate.now().minusDays(30);
Files.walk(reportDir)
.filter(Files::isRegularFile)
.filter(p -> isOlderThan(p, cutoff))
.forEach(p -> moveToArchive(p, archiveDir));
}
CI/CD Integration¶
GitLab CI Artifacts¶
GitHub Actions¶
- name: Upload reports
uses: actions/upload-artifact@v3
with:
name: fhir-test-reports
path: target/fhir-reports/
retention-days: 30
Store in S3¶
public class S3ReportStorage implements ReportStorage {
private final AmazonS3 s3Client;
private final String bucketName;
@Override
public void store(TestReport report, String format) {
String key = "reports/" + report.getId() + "." + format;
String content = fhirContext.newJsonParser()
.encodeResourceToString(report);
s3Client.putObject(bucketName, key, content);
}
}
Security¶
Encrypt Reports¶
public class EncryptedStorage implements ReportStorage {
private final ReportStorage delegate;
private final Cipher cipher;
@Override
public void store(TestReport report, String format) {
String json = fhirContext.newJsonParser()
.encodeResourceToString(report);
byte[] encrypted = cipher.doFinal(json.getBytes());
// Store encrypted bytes
}
}
Access Control¶
// Restrict report access
testReport.getMeta().addSecurity()
.setSystem("http://terminology.hl7.org/CodeSystem/v3-Confidentiality")
.setCode("R")
.setDisplay("Restricted");
Best Practices¶
Multiple Storage
Use composite storage to save reports both locally and on a server for redundancy.
Disk Space
Implement retention policies to prevent disk space issues from accumulated reports.
- Backup reports - Store in multiple locations
- Implement retention - Delete or archive old reports
- Secure storage - Encrypt sensitive test data
- Monitor space - Alert on low disk space
- Version reports - Track report format changes
Next Steps¶
- Generation - Report generation
- Overview - TestReport basics