/f/151162/1080x1080/1ff188ea6d/automation-star-2026-06-23t111438-577.png)
Our current test automation framework uses Cucumber, Rest Assured, and Spring Boot. Because of how our CI/CD pipeline was set up, we could only manage one testing project. When we needed to add performance and load testing with Gatling, the challenge became clear: integrate Gatling into the existing framework without starting a new project.
What seemed simple at first soon uncovered several technical hurdles that needed careful planning and step-by-step problem-solving.
The first issue came up right away. Gatling simulations could not resolve Spring beans like the existing Cucumber framework.
This limitation meant I could not directly reuse:
Existing API endpoint configurations
Request and response models
Shared framework components
Without access to these components, I would face a lot of code duplication, which I wanted to avoid.
While looking for solutions, I recalled that Cucumber supports multiple runners with various configurations.
This inspired a new idea.
Instead of trying to fit Gatling into the current setup, I created:
A dedicated package for Gatling simulations
A separate StressRunner
A parent CucumberRunner to manage execution
The goal was to allow functional tests and performance tests to work together in the same project while keeping them logically separated.
After setting up the runners, another challenge arose.
Our tests depended on shared test data. Since both the functional tests and Gatling simulations accessed the same data sources, concurrency problems began to emerge.
Running both suites at once led to data conflicts and inconsistent test behavior.
To solve this, I took a step back and reevaluated the execution flow.
The solution was surprisingly straightforward.
I implemented a hook that tracked the completion of the main Cucumber execution. Once all functional tests finished, the hook automatically triggered the Gatling stress tests.
This approach provided several benefits:
Functional and performance tests no longer competed for the same data.
Existing test data could still be reused.
The framework stayed as a single project, meeting CI/CD requirements.
Gatling simulations could run reliably alongside Cucumber features.
This was the first major milestone where the integration started to work as intended.
Although the technical integration was done, another need came up.
The development team wanted to use load tests not only for performance checks but also for debugging.
At first, the Gatling simulations were hardcoded:
Fixed scenarios
Fixed durations
No runtime customization
This made them less flexible and hard to use for investigating specific issues.
To address this, I added dedicated Gatling step definitions within Cucumber.
These steps allowed users to define:
Number of concurrent users
Target endpoints
Test duration
Additional simulation parameters
As a result, performance tests became configurable directly from feature files, making them much more helpful for developers needing to reproduce and debug issues under load.
By carefully implementing each layer step by step, the framework evolved into a solution where:
Functional testing and load testing coexist in a single project.
Gatling simulations can run after Cucumber scenarios.
Test data conflicts are avoided.
Developers can configure load tests through Cucumber features.
Existing framework components can still be used where appropriate.
Most importantly, developers gained an easy way to reproduce performance-related issues and validate fixes more effectively.
The biggest lesson from this project was not technical—it was methodological.
When faced with a complex integration challenge, avoid jumping in with the complete end goal in mind. Instead:
Start with the smallest possible working solution.
Validate that it works.
Expand gradually.
Tackle problems one layer at a time.
By focusing on small, achievable steps rather than the whole problem at once, what initially seemed like a tough integration became a successful and manageable solution.
Start small, make it work, and then build on it.