SDLC Automation · Topic 3 of 6
Automated Testing in Pipelines
Add unit, integration, load and security tests to CI/CD pipelines, gate promotion on results and roll back automatically when alarms fire after deployment.
- 5 min
- A non zero exit code from a command fails the CodeBuild action and stops the pipeline.
- CodeBuild reports store JUnit and similar results for trend history.
- Use the CodePipeline Test category for CodeBuild test runs and Device Farm for device and browser tests.
What it is
Automated testing in a pipeline means every change is checked by code, not by a person, before it can reach production. Tests run at several points: before the build finishes, after a deploy to a test environment, and after the release to production.
The aim is fast feedback and a safe gate. A failed test stops the pipeline, so a bad change never reaches the next stage.
How it works
The test layers
Put cheap, fast tests first and expensive ones later. This is the idea behind the test pyramid.
| Layer | Where it runs | Typical tool |
|---|---|---|
| Static analysis and linting | Build stage | CodeBuild commands, cfn-lint |
| Unit tests | Build stage | Test framework in CodeBuild |
| Dependency and secrets scanning | Build stage | Third party scanners, Amazon Inspector for images |
| Integration tests | After deploy to test | CodeBuild test action, Lambda invoke action |
| Load and performance tests | Staging | Load tool run from CodeBuild |
| UI and device tests | Staging | AWS Device Farm |
| Smoke and synthetic tests | After production deploy | CloudWatch Synthetics canaries |
CodeBuild as the test runner
In CodePipeline a CodeBuild action can sit in the Build category or the Test category. If a command returns a non zero exit code the build fails, and the stage and the pipeline stop. Test result files are published as reports, so you can see trends even when the build passes.
version: 0.2
phases:
build:
commands:
- pytest --junitxml=report.xml
reports:
pytest-results:
files:
- report.xml
file-format: JUNITXML
Running tests on pull requests and merges
Validate a change before it merges, not only after. Three common triggers exist.
| Trigger | How |
|---|---|
| CodeBuild webhook | For GitHub, GitHub Enterprise and Bitbucket sources. Filter groups match the event type (PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED, PULL_REQUEST_MERGED, PUSH) and can match the target branch |
| CodePipeline V2 trigger | A V2 pipeline can start on pull request events, with branch filters, for a connection based source |
| EventBridge rule | Matches a CodeCommit "Pull Request State Change" event (created or source branch updated) and starts a CodeBuild project |
aws codebuild create-webhook --project-name app-tests \
--filter-groups '[[{"type":"EVENT","pattern":"PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED"},{"type":"BASE_REF","pattern":"^refs/heads/main$"}]]'
Report the result back to the pull request so reviewers see it. With a webhook, CodeBuild posts the build status to the source provider. With CodeCommit, a Lambda function or the build itself can add a comment to the pull request or update its approval state.
Use a merge trigger (for example PUSH on the main branch) for the full pipeline, and a lighter pull request trigger for fast unit tests only.
Testing after a deploy
An integration test needs a running environment. The usual pattern is to deploy to a test stack, run a CodeBuild action against its endpoint, and then tear the stack down or keep it for the next run.
A Lambda function in an Invoke action suits small custom checks, such as calling a health URL and reporting success or failure back to the pipeline.
Testing inside the deployment
CodeDeploy can run tests as part of the deploy itself.
- On EC2, the
ValidateServicehook runs a script after the application starts and can fail the deployment. - For Lambda and ECS, the traffic hooks (
BeforeAllowTrafficandAfterAllowTraffic, plusAfterAllowTestTrafficfor ECS) call a Lambda function that tests the new version. - CodeDeploy can watch CloudWatch alarms during a deployment and stop and roll back when one enters the ALARM state.
This turns production monitoring into the last test: a canary release sends a small share of traffic to the new version while alarms judge its health.
Security testing
Shift security checks left, which means running them early in the pipeline.
- Scan source and dependencies in the build for known vulnerable packages and committed secrets.
- Scan container images in Amazon ECR, using either the basic scan or Amazon Inspector enhanced scanning.
- Validate infrastructure templates before deploy with tools such as cfn-lint and CloudFormation Guard.
- Use AWS CloudFormation Hooks to block noncompliant resources at deploy time.
Gates and approvals
A gate can be automatic (tests must pass, alarms must be clear) or manual (an approval action). Use automatic gates for repeatable rules and manual approval where a business decision is needed. Many teams use a manual approval only for the production step.
Test data and isolation
Tests should not depend on shared long lived state. Give each pipeline run its own test stack or its own data prefix, and use short lived credentials from the pipeline role.
What to remember for the exam
- A non zero exit code from a command fails the CodeBuild action and stops the pipeline.
- CodeBuild reports store JUnit and similar results for trend history.
- Use the CodePipeline Test category for CodeBuild test runs and Device Farm for device and browser tests.
- CodeDeploy hooks and CloudWatch alarms provide validation and automatic rollback.
- Amazon Inspector scans ECR images and also Lambda functions and EC2 instances.
- CloudWatch Synthetics canaries test an endpoint continuously after release.
- Put fast tests early and slow tests later to fail fast.
- A Lambda invoke action runs custom test logic and reports back to the pipeline.
When a question asks for the least operational effort to stop a bad deployment automatically, choose CodeDeploy alarm based rollback over a custom monitoring script.
Common mistakes
Testing only in production. Waiting for users to find defects defeats the pipeline.
Running every test in one stage. Slow integration tests then delay feedback from quick unit tests.
Treating a manual approval as testing. A human click does not prove the change works.
Sharing one test environment. Parallel pipeline runs overwrite each other's data and give flaky results.
Tests that call production data stores or use production credentials can cause the very incident the pipeline is meant to prevent.
Check yourself
Where do you put a fast unit test and where a slow load test?
Unit tests go in the build stage for quick feedback, and load tests run later against a staging deployment.
How can a deployment roll back without human action?
CodeDeploy watches CloudWatch alarms and rolls back automatically if one goes into ALARM.
Which service tests a web application on real browsers and devices?
AWS Device Farm, used as a Test action in CodePipeline.
Topic 3 of 6 in SDLC Automation
Test yourself on SDLC Automation
The full AWS DOP-C02 question bank has 844 questions, with timed practice exams and an explanation for every answer.
This study guide is independent and is not affiliated with, endorsed by, or sponsored by AWS. Vendor names, certification names and exam codes are trademarks of their respective owners and are used for identification only.