At EDSTEM, we've made significant strides in improving our testing infrastructure by adopting Testcontainers as our go-to solution for managing test dependencies. This adoption has transformed how we approach integration testing and has brought newfound reliability to our test suites.
Why We Chose Testcontainers
Our development teams work with a diverse tech stack, and maintaining consistent test environments across different services was becoming increasingly challenging. Testcontainers offered us an elegant solution by providing:
- Consistent environments across local development machines and CI pipelines
- Language-agnostic support that works well with our polyglot architecture
- Wide range of pre-configured modules for common dependencies
- Docker-based isolation ensuring clean test runs every time
Our Implementation Journey
Database Testing
One of our first implementations was with database testing. Previously, we relied on in-memory databases for testing, which sometimes behaved differently from our production PostgreSQL instances. With Testcontainers, we now spin up actual PostgreSQL containers for our tests:
@Container
public static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:14.1")
.withDatabaseName("integration-tests-db")
.withUsername("test")
.withPassword("test");
This approach ensures our tests run against the same database version we use in production, eliminating any environment-specific issues.
Microservices Testing
For our microservices architecture, Testcontainers has been invaluable. We use it to:
- Test service interactions with Redis caching
- Verify message processing with RabbitMQ containers
- Simulate AWS services using LocalStack containers
UI Testing Infrastructure
The recent addition of browser testing support in Testcontainers has been particularly exciting for our frontend team. We now run Selenium tests using containerized Chrome and Firefox instances:
@Container
public static BrowserWebDriverContainer<?> chrome = new BrowserWebDriverContainer<>()
.withCapabilities(new ChromeOptions());
Desktop Client: A Game Changer
The release of the Testcontainers Desktop client has been transformative for our development workflow. Our teams particularly appreciate:
- Visual management of test containers and resources
- Easy debugging of container states during test runs
- Resource monitoring to optimize test performance
- Simplified setup for complex testing scenarios
Best Practices We've Developed
Through our experience with Testcontainers, we've established several best practices:
- Resource Management
- Use container groups for related services
- Implement proper cleanup procedures
- Monitor resource usage in CI pipelines
- Performance Optimization
- Reuse containers where possible
- Implement parallel test execution
- Utilize container networks for service communication
- Configuration Management
- Maintain consistent container versions
- Use environment variables for configuration
- Document container dependencies
Challenges and Solutions
While our journey with Testcontainers has been largely positive, we've encountered and solved several challenges:
Challenge 1: CI Pipeline Duration
Initially, our CI pipelines slowed down due to container startup times. We solved this by:
- Implementing container reuse strategies
- Optimizing container configurations
- Parallelizing independent test suites
Challenge 2: Resource Consumption
To address high resource usage, we:
- Implemented container cleanup policies
- Optimized container specifications
- Monitored resource metrics
Future Plans
Looking ahead, we're excited about:
- Expanding our use of Testcontainers Desktop for more complex testing scenarios
- Implementing new modules as they become available
- Contributing back to the Testcontainers community
- Developing custom modules for our specific needs
Conclusion
Testcontainers has become an integral part of our testing infrastructure at EDSTEM. It's not just a testing tool; it's a key component of our quality assurance strategy. The introduction of the desktop client has further enhanced our testing capabilities, and we're looking forward to leveraging more of its features as our testing needs evolve.
By standardizing our test environments with Testcontainers, we've significantly improved our test reliability and developer productivity. The investment in this technology has paid off through reduced bug incidents in production and faster development cycles.