Stage 5 · Platform
Testing & Quality Gates
Unit Tests in CI
Running Jest, pytest, go test, and JUnit reports with deterministic fixtures and parallel workers.
Unit Test Principles in CI
Unit tests are the first line of defense in a CI pipeline. They run fast, provide immediate feedback, and catch regressions before they reach integration tests. A good unit test suite runs in under 2 minutes and covers the critical paths of your application.
The key principles for unit tests in CI are determinism, speed, and isolation. Tests must produce the same result every time, run quickly to keep the pipeline fast, and not depend on external services or shared state.
Jest in CI
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
- run: npm ci
- name: Run Jest
run: |
npx jest --ci --reporters=default --reporters=jest-junit
env:
JEST_JUNIT_OUTPUT_DIR: ./test-results
JEST_JUNIT_OUTPUT_NAME: junit.xml
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: jest-results
path: test-results/
- name: Publish test results
uses: dorny/test-reporter@v1
if: always()
with:
name: Jest Unit Tests
path: test-results/junit.xml
reporter: java-junitThe --ci flag enables Jest CI mode, which fails on console warnings and disables interactive features. The jest-junit reporter outputs JUnit XML for GitHub Actions integration. if: always() uploads results even when tests fail.
Pytest in CI
test:unit:
stage: test
image: python:3.12
cache:
key:
files:
- requirements.txt
paths:
- .venv/
script:
- python -m venv .venv
- source .venv/bin/activate
- pip install -r requirements.txt
- pip install pytest pytest-cov pytest-xdist
- pytest tests/unit/
--junitxml=test-results/junit.xml
--cov=src/
--cov-report=xml:coverage/cobertura.xml
--cov-report=html:coverage/html/
--cov-fail-under=80
-n auto
artifacts:
when: always
reports:
junit: test-results/junit.xml
coverage_report:
coverage_format: cobertura
path: coverage/cobertura.xml
paths:
- coverage/pytest-xdist with -n auto parallelizes tests across CPU cores. --cov-fail-under=80 enforces a minimum coverage threshold. The Cobertura report renders in GitLab merge requests. Artifacts include both the report and the HTML coverage output.
Go Test in CI
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.22"
- name: Run tests
run: |
go test -race -coverprofile=coverage.out -covermode=atomic ./...
go tool cover -func=coverage.out
- name: Check coverage threshold
run: |
COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | tr -d '%')
echo "Total coverage: $COVERAGE%"
if (( $(echo "$COVERAGE < 70" | bc -l) )); then
echo "::error::Coverage $COVERAGE% is below 70% threshold"
exit 1
fi
- name: Upload coverage
uses: actions/upload-artifact@v4
with:
name: coverage
path: coverage.outThe -race flag enables the Go race detector to catch data races. -covermode=atomic provides accurate coverage for concurrent code. The threshold check uses bc for floating-point comparison and fails the pipeline if coverage drops below 70%.
Test Parallelism
Running tests in parallel reduces pipeline duration. Most test frameworks support parallel execution, but tests must be designed for it — no shared mutable state, no port conflicts, and no order dependencies.
For test suites that take over 5 minutes, use matrix builds to split tests across multiple runners. Jest supports --shard, pytest supports pytest-xdist, and Go supports -count with test binary partitioning.
Flaky Test Management
Flaky tests erode trust in the pipeline. When tests fail intermittently, developers start ignoring failures or re-running pipelines. Track flaky tests, quarantine them, and fix the root cause.
- Track flaky tests — use test analytics to identify tests with intermittent failures.
- Quarantine flaky tests — move them to a separate suite that runs but does not block merging.
- Fix the root cause — most flakes come from shared state, network dependencies, or timing issues.
- Set a flaky test budget — reject PRs that introduce new flaky tests.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.