Software Testing CI/CD and Testing
CI/CD stands for Continuous Integration and Continuous Delivery (or Deployment). It is a modern software delivery practice where code changes are automatically built, tested, and prepared for release multiple times a day. Testing is the backbone that makes CI/CD safe and reliable.
What CI/CD Means
CONTINUOUS INTEGRATION (CI)
────────────────────────────────────────────────────────
Developer pushes code → Code is automatically:
1. Built (compiled / packaged)
2. Unit tested
3. Integration tested
4. Code quality checked
→ All within minutes of the code push
CONTINUOUS DELIVERY (CD)
────────────────────────────────────────────────────────
After CI passes → Code is automatically:
5. Deployed to a staging environment
6. Acceptance / smoke tested
7. Ready for manual approval to go to production
CONTINUOUS DEPLOYMENT
────────────────────────────────────────────────────────
After all tests pass → Code is automatically:
8. Deployed to production — no human approval needed
The CI/CD Pipeline
Developer pushes code to repository
│
▼
┌──────────────────────────────────────────────────────┐
│ CI/CD PIPELINE │
│ │
│ [Build] → [Unit Tests] → [Integration Tests] │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ Fail → Fail → Fail → │
│ Notify Notify Notify developer │
│ team team to fix before │
│ code advances │
│ ▼ │
│ [Deploy to Staging] → [Smoke Tests] → [UAT] │
│ │ │
│ ▼ │
│ [Deploy to Production] │
└──────────────────────────────────────────────────────┘
How Testing Fits at Each Stage
Stage 1: Pre-Commit (Local)
Before pushing code, the developer runs unit tests locally. Some teams use git hooks to automatically block commits that fail tests.
Stage 2: Build Stage
The CI server compiles the code. If the build fails, the pipeline stops immediately and notifies the team.
Stage 3: Unit Test Stage
The full unit test suite runs automatically. Any failure blocks the pipeline. This stage typically runs in under 5 minutes.
Stage 4: Integration Test Stage
Integration tests run against the built application. Database connections, API contracts, and service interactions are verified.
Stage 5: Static Code Analysis
Tools like SonarQube scan the code for security vulnerabilities, code smells, duplication, and style violations — automatically.
Stage 6: Staging Deployment
Code is deployed to a staging environment that mirrors production. Smoke tests and regression tests run here.
Stage 7: Performance and Security Tests
Longer-running tests — load tests, security scans — run on the staging environment. These may run on a scheduled basis rather than every commit.
Stage 8: Production Deployment
Code reaches production. Post-deployment smoke tests confirm the live system works after the deployment.
The Test Pyramid in a CI/CD Context
/\
/ \
/E2E \ ← Few, slow, run less often
/──────\
/ API \ ← Medium count, run every build
/──────────\
/ Unit Tests \ ← Many, fast, run on every commit
──────────────
In CI/CD:
Unit tests: Run on every push (seconds)
API/Integration: Run on every build (minutes)
E2E Tests: Run before staging deploy (minutes to hours)
Performance: Run nightly or before release (hours)
Popular CI/CD Tools
TOOL DESCRIPTION ──── ─────────── GitHub Actions Built into GitHub; YAML-based pipeline config Jenkins Open-source, highly customisable CI server GitLab CI/CD Built into GitLab with powerful pipeline features CircleCI Cloud-based CI/CD with fast parallel testing Azure Pipelines Microsoft's CI/CD for Azure DevOps Bitbucket Pipelines Built into Atlassian's Bitbucket
A Simple GitHub Actions Pipeline with Tests
name: CI Pipeline
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: npm install
- name: Run unit tests
run: npm test
- name: Run integration tests
run: npm run test:integration
- name: Deploy to staging
if: success()
run: ./deploy-staging.sh
Benefits of Testing in CI/CD
- Bugs are found within minutes of the code that caused them being written.
- No code reaches production without passing automated quality checks.
- The team gets a constant, objective signal of software quality after every change.
- Releases become low-risk because every change was tested before it was merged.
- Manual testing effort is focused on exploratory and UAT work rather than repetitive regression checks.
