Best Practices
This document provides recommendations for effective testing with SmileCdrContainer
and SmileHarness
. Following these best practices will help you write more efficient, reliable, and maintainable tests.
Starting and stopping Docker containers is resource-intensive. When writing multiple tests that use the same container configuration, consider using a shared container instance:
@Testcontainers
class MyTestSuite {
// Shared container for all tests in this class
@Container
private static final SmileCdrContainer container = new SmileCdrContainer("2025.02.R02");
private static SmileHarness harness;
@BeforeAll
static void setup() {
harness = container.getHarness();
}
@Test
void test1() {
// Use the shared container and harness
}
@Test
void test2() {
// Use the same shared container and harness
}
}
Note that since the SmileCdrContainer is defined as static
, it will be reused through the entire test class. Important to note that any data stored by one test will be accessible by another. This may not be what you want, so it is important to consider which lifecycle to use.
Consider the appropriate lifecycle for your container:
@Container
on a static
field to share a container across all tests in a class.@Container
on a non-static field to create a fresh isolated container for each individual test.Choose based on whether your tests need isolation or can share state.
Docker containers can take time to start, especially for complex applications like Smile CDR. Set appropriate timeouts to avoid test failures due to slow startup:
SmileCdrContainer container = new SmileCdrContainer("2025.02.R02")
.withStartupTimeout(Duration.ofMinutes(5));
Each test should focus on testing a specific functionality:
@Test
void testPatientCreation() {
// Test only patient creation
}
@Test
void testPatientSearch() {
// Test only patient search
}
Avoid writing tests that try to test too many things at once, as they become difficult to maintain and debug.
Use descriptive names for your tests that clearly indicate what is being tested:
@Test
void testCreatePatientWithMultipleIdentifiers() {
// Test creating a patient with multiple identifiers
}
Create helper methods or classes for generating test data to make your tests more readable and maintainable:
private Patient createTestPatient() {
Patient patient = new Patient();
patient.addName().setFamily("Test").addGiven("Patient");
patient.setGender(Enumerations.AdministrativeGender.MALE);
return patient;
}
Create clients once and reuse them throughout your tests to avoid unnecessary overhead:
private static IGenericClient fhirClient;
private static AdminJsonRestClient adminClient;
@BeforeAll
static void setup() {
harness = container.getHarness();
fhirClient = harness.getSuperuserFhirClient();
adminClient = harness.getAdminJsonClient();
}
Use the appropriate level of authentication for your tests:
getSuperuserFhirClient()
for administrative tasksgetFhirClient()
with custom authentication for testing specific user scenariosFor tests that require specific configurations, use custom properties files:
SmileCdrContainer container = new SmileCdrContainer()
.withPropertiesFile("custom-config.properties");
This allows you to tailor the Smile CDR configuration to your specific test needs.
Starting and stopping containers is expensive. Design your tests to minimize container restarts:
@TestMethodOrder
to control test execution order when necessaryTestcontainers supports parallel test execution, but be careful with resource usage:
Smile CDR can be resource-intensive. Make sure your test environment has sufficient resources:
Use the Testcontainers API to inspect the container state:
// Get container logs
String logs = container.getLogs();
// Execute a command in the container
ExecResult result = container.execInContainer("ls", "-la");
By default, SmileCdrContainer is considered started when the "You are up and running" log message arrives in the logs. However, you can use custom wait strategies to ensure the container is fully ready before tests, if you have some alternate start conditions.
SmileCdrContainer container = new SmileCdrContainer("2025.02.R02")
.waitingFor(Wait.forHttp("/Patient")
.forPort(8000)
.withBasicCredentials("admin", "password")
.forStatusCode(200));
By following these best practices, you can write more effective tests with SmileCdrContainer
and SmileHarness
. Remember that good tests are:
You are about to leave the Smile Digital Health documentation and navigate to the Open Source HAPI-FHIR Documentation.