GSoC 2026 Project Thread: Backend Integration Testing Standardization and Expansion

Hello OpenELIS Community!

I will be giving my updates on the Backend Integration Testing project for GSoC 2026. Building on the foundation laid during the contributions from the previous couple of years where we established the core infrastructure and reached a 28% coverage baseline, this year’s project aims to scale up significantly, targeting a 60%+ coverage goal for all critical backend components.

Project Goal

This project aims at extending and creating more Integration Tests to achieve a Test Coverage of at least 60% for the Backend Service and Controller Layer

To standardize the backend integration testing workflow, increase test coverage across the 5-layer architecture (Service, DAO, Controller), and implement complex workflow-based integration tests using modern infrastructure (Testcontainers, DBUnit)

Project Background (Evolved from previous community contributions)

For the 2 last years, we established a Dataset-Driven Testing Strategy, ensuring realistic scenarios by using actual data instead of mocks. This year, we are moving beyond simple CRUD tests to focus on deep business logic and cross-component interactions.

Current Gaps

After an initial analysis of the current state, I’ve identified several key areas for GSoC 2026:

  1. Controller Layer Coverage: Many REST and Spring MVC controllers are currently excluded from component scanning in the test context (AppTestConfig) to prevent circular dependencies. This leaves a gap in testing the web layer’s interaction with the service layer.
  2. Infrastructure Mocking Boundaries: While we successfully mock external services (FHIR, Odoo, Mail) for isolation, we lack standardized patterns for verifying the outgoing data structure to these systems.
  3. Complex Workflow State: Most tests reset the database state between methods. This makes it difficult to test multi-step laboratory workflows (e.g., Sample Receipt → Analysis → Result → Validation → Release) as a single cohesive unit.
  4. Data Setup Friction: Manually creating DBUnit XML datasets for complex entities like Samples and Patients remains a bottleneck.
  5. Standardization: Some older integration tests do not yet follow the “Gold Standard” (based on MenuServiceTest.java), leading to inconsistent test reliability.

Proposed Implementation Plan

My project will be divided into the following key milestones:

Milestone 1: Infrastructure & Standardization

  • Refactor AppTestConfig to support more granular bean registration, allowing more controllers to be tested via MockMvc.
  • Audit and migrate existing integration tests to the BaseWebContextSensitiveTest standard.
  • JaCoCo Integration: Ensure JaCoCo is strictly measuring and tracking coverage for all newly added tests to maintain data-driven progress.

Milestone 2: Core Service & Controller Expansion

  • Increase integration test coverage for the Patient, Sample, and Result modules.
  • Ensure comprehensive coverage of CRUD operations, data retrieval, business logic validation, and error handling.
  • Goal: Happy-path and error-path integration tests for every REST endpoint in these modules.

Milestone 3: Complex Workflow Testing

  • Implement “Scenario Tests” that simulate full laboratory cycles.
  • Develop shared datasets (full-lab-workflow.xml) that can be used across multiple test suites to ensure data integrity across the entire stack.

Milestone 4: Tooling & Documentation

  • Explore/Implement a Java-based DSL or Builder pattern for generating test data dynamically.
  • Finalize the “OpenELIS Integration Testing Handbook” for future contributors.

Stay Updated

I will be documenting my journey, technical hurdles, and milestones regularly. You can follow my progress and read detailed deep-dives on my Medium blog.

:light_bulb: Discussion Points

I would love to hear from mentors and community members:

  • Are there specific “high-risk” modules that you feel are currently under-tested?
  • What are the most common “integration bugs” you’ve encountered that unit tests missed?
  • Any preferences on data generation tools?

Looking forward to your feedback and ideas
cc: @Herbert @pmanko @Moses_Mutesasira @reagan @tasksolver @mherman22

3 Likes

Milestone 1 Update: Integration Test Dataset Audit Results

Hi everyone
As promised in Milestone 1, I’ve completed the first phase of the audit: identifying which existing integration tests follow the “Gold Standard” (MenuServiceTest.java) and which ones still need to be brought in line.

What I Audited

I scanned every test class that extends BaseWebContextSensitiveTest and checked whether it calls executeDataSetWithStateManagement(...) in a @Before method to seed a known, isolated database state.

The convention is:

java

@Before

public void init() throws Exception {

executeDataSetWithStateManagement("testdata/<module>.xml");

}

The Finding: 40 Tests Are Missing Datasets

I found 40 integration tests that inherit the full Spring + Testcontainers + Liquibase context (via BaseWebContextSensitiveTest) but have no dataset loading at all. This means they run against an unknown or empty database state, making their results unreliable.

Some create data programmatically inside @Before or @Test (which bypasses isolation), and in one case, ShippingBoxServiceTest.java even has a comment in the code itself that says:

“Note: This test would require test data setup via @Before method”


Affected Tests (40 total, grouped by module)

Analyzer Module (18 tests)

analyzer/AnalyzerColumnMappingTest.java

analyzer/DatabaseSchemaValidationTest.java

analyzer/UnitMappingColumnMappingTest.java

analyzer/controller/AnalyzerDefaultsRestControllerTest.java

analyzer/controller/AnalyzerMappingPreviewRestControllerTest.java

analyzer/controller/AnalyzerPluginConfigRestControllerTest.java

analyzer/controller/AnalyzerRestControllerTest.java

analyzer/controller/AnalyzerSecurityTest.java

analyzer/controller/AuthenticatedAnalyzerControllerTest.java

analyzer/genexpert/GeneXpertFileIntegrationTest.java

analyzer/genexpert/GeneXpertHL7IntegrationTest.java

analyzer/mindray/MindrayBA88AIntegrationTest.java

analyzer/service/AnalyzerErrorServiceIntegrationTest.java

analyzer/service/AnalyzerFieldMappingServiceIntegrationTest.java

analyzer/service/AnalyzerMappingAuditTest.java

analyzer/service/AnalyzerQueryServiceIntegrationTest.java

analyzer/service/AnalyzerQueryServiceStoreFieldsIntegrationTest.java

analyzer/service/CustomFieldTypeValidationIntegrationTest.java

AnalyzerImport Module (5 tests)

analyzerimport/action/AnalyzerFhirImportControllerTest.java

analyzerimport/analyzerreaders/ASTMAnalyzerReaderIdentificationTest.java

analyzerimport/analyzerreaders/HL7AnalyzerReaderTest.java

analyzerimport/analyzerreaders/StagoSTart4MessageProcessingIntegrationTest.java

analyzerimport/controller/AnalyzerImportControllerHL7Test.java

Patient Module (3 tests)

patient/daoimpl/PatientDAORedirectIntegrationTest.java

patient/merge/dao/PatientMergeAuditDAOTest.java

patient/merge/service/PatientLookupRedirectTest.java

Storage Module (DAO Layer 3 tests)

storage/dao/StorageDeviceDAOTest.java

storage/dao/StorageRackDAOTest.java

storage/dao/StorageShelfDAOTest.java

Other Modules (11 tests)

alert/service/AlertNotificationServiceTest.java

barcode/BarcodeConfigurationRestControllerTest.java

common/provider/validation/NonConformityRecordNumberValidationProviderTest.java

ocl/OclZipImporterIntegrationTest.java

plugin/StagoSTart4PluginIntegrationTest.java

qc/service/WestgardRuleConfigServiceIntegrationTest.java

reports/controller/BaseReportRestControllerTest.java

shipment/ShippingBoxServiceTest.java

shipment/UnassignedSampleServiceTest.java

sitebranding/controller/rest/SiteBrandingRestControllerTest.java

sitebranding/dao/SiteBrandingDAOTest.java

Why This Matters Before We Add More Tests

  1. Coverage numbers are misleading JaCoCo counts these as “tested” code paths even when the test isn’t actually asserting anything meaningful against real data.
  2. No isolation tests that create data programmatically can leave state that causes other tests to fail intermittently.
  3. Harder to extend any new test we add on top of these modules will inherit the same fragile patterns if we don’t fix the baseline first.

My Proposed Plan of Action

I’d like to treat these 40 tests as a prerequisite cleanup before expanding coverage (aligns directly with Milestone 1 “Audit and migrate existing integration tests to the BaseWebContextSensitiveTest standard”).

I am taking ownership of:

  • Analyzer module (18 tests)
  • AnalyzerImport module (5 tests)

For each test, the fix is:

  1. Create src/test/resources/testdata/<module>.xml (DBUnit Flat XML with minimum required records)
  2. Add @Before public void init() calling executeDataSetWithStateManagement("testdata/<module>.xml")
  3. Remove any programmatic data creation and replace with references to seeded records
  4. I have created a summurised report of the current structure of our current tests
    @Herbert @Moses_Mutesasira @mherman22 @pmanko
    Happy to answer any questions.
1 Like

Hello everyone,

Quick update covering the bonding period and the start of Week 1 of coding.

Bonding period

During the bonding period I focused on understanding the testing infrastructure, and working on some early integration testing tasks. I also wrote a short reflection on what I learned during that phase especially around collaboration and how tests are structured in the project.

Read the blog post — Agaba Derrick on Medium

Week 1 of coding (what’s underway)

We’re now in the first week of the coding period. So far:

  • Had a strategy session with my mentor @Herbert on how to approach the testing work going forward.
  • Continuing integration testing working on fixture stabilisation and improving dataset consistency.
  • Strengthening test coverage across key service-layer components.
  • Raised several pull requests around test improvements and codebase cleanup.

Pull Requests

Raised multiple PRs this week targeting test improvements and codebase cleanup:

CC: @Moses_Mutesasira @mherman22 @pmanko

1 Like