I’m curious to learn about different approaches teams are taking to integrate testing into their CI/CD pipelines and ensure reliable deployments across environments.
In our current setup, we’ve structured our pipeline so that automated tests execute after every commit/merge to the respective environment branches. This gives us immediate feedback on code quality and helps catch issues early in the development cycle. Our tests run progressively through environments, unit and integration tests on dev commits, followed by more comprehensive functional and regression suites as code promotes through staging, UAT and production.
However, I’ve encountered teams where the testing team maintains completely separate pipelines that run independently of the main deployment flow. Some trigger these via nightly jobs, while others rely on manual execution when they feel it’s necessary.
Personally, I find the manual approach somewhat counterproductive to the core principles of automation. The whole point of CI/CD is to get quick, consistent feedback on our changes. When testing becomes a manual gate or an afterthought that runs hours later, we lose that immediate feedback loop that helps developers address issues while the context is still fresh in their minds.
I’m interested in hearing how others have tackled this challenge:
How tightly integrated are your testing processes within your deployment pipeline?
Do you run different test suites at different pipeline stages?
How do you balance test execution time with the need for quick feedback?
Looking forward to learning from your experiences and approaches!
In my experience, the stronger CI/CD pipeline is the one that has testing integrated into the deployment flow rather than a separate, optional step.
Our approach is to layer our tests so feedback can be fast in the beginning, yet without compromising the overall speed. For example:
On each commit/merge into a feature or dev branch → fast unit and API-level integration testing.
On staging/UAT promotion → full functional, regression, and exploratory automation wherever applicable.
Before production → a very small, critical set of smoke testing verifying key paths.
So most of the breakage gets caught in the early stages, while the heavy suites run closer to release, aiming for fail fast, trust the go-live.
I have been seeing and even tried the separate nightly pipeline, but in practice: it does nothing but extend the feedback loop, meaning defects emerge when the developer has already moved on mentally from that code. When integrated tightly, the loop shortens, sustaining quality without any bottlenecks.
In the end, the balance is all about test prioritization. It is not about running everything at every stage; rather, it is about running the right things at the right time to maximize speed and confidence.
In our setup the test suites are not connected directly with the pipeline after every merge. We run them manually and pick based on the need. Sometimes it is a smoke sheet, sometimes a sanity suite and sometimes a full regression. Mostly we run these once a day or at most twice, not after every commit.
Earlier we were doing automation on a project basis. A few months ago it shifted to a microservices model where each team has to automate their own service. Because of this the automation with Playwright and JavaScript using Cucumber is still in progress and not fully linked with CI/CD yet.
For releases we usually run the sanity build on staging and the regression on UAT. Before deploying a new build we create some backward compatibility test cases and run them. After deployment we take the applications to terminal state and complete the checks. On UAT the client also does their testing. Once backward compatibility is cleared we deploy the final sanity build on staging and run the sanity suite again. If everything passes then sign off is given and staging is frozen for the next week as the client shifts there for testing of the new build.
One of the major challenges is the test environment. Since different services are deployed there at different times, test cases often fail because features are still in progress. To avoid getting blocked we redeploy the build on another environment and continue testing there.
Our pipeline also has one different step. We first create the Docker image and then make the build on Jenkins. It is the reverse of what many teams do but it works for how we package and deploy our services.
At this stage our process is more controlled than fast. It is not perfect and we face issues like slow feedback and unstable environments. But as the automation framework grows we plan to bring more testing into the pipeline itself instead of keeping it separate.