How do I run tests in a CI pipeline?
Basic Pipeline Structure
A typical CI pipeline has stages: checkout code, install dependencies, run tests, and optionally build or deploy. The test step usually runs a command like npm test, pytest, or go test ./... depending on your language. Most CI services (GitHub Actions, GitLab CI, Jenkins, CircleCI) let you define this in a YAML file.
The pipeline should treat a non-zero exit code from the test command as a failure. That stops the pipeline and notifies the team. You can also split tests into unit, integration, and end-to-end stages, running faster tests first to give quick feedback.
- Checkout code
- Install dependencies (cache them for speed)
- Run unit tests
- Run integration or end-to-end tests
- Publish test results as artifacts
Practical Tips
Cache dependencies between runs to avoid reinstalling everything each time. Use a clean environment or container to ensure tests are reproducible. Set a timeout so a hung test doesn't block the pipeline forever.
If you have flaky tests, quarantine them or fix them quickly; a pipeline that fails randomly erodes trust. For parallel test execution, many CI systems support splitting tests across multiple jobs.
Common mistakes
- Running tests only on the main branch instead of every pull request, which lets broken code merge.
- Ignoring test failures or marking them as allowed to fail, which defeats the purpose of CI.
- Not caching dependencies, making pipelines slow and expensive.
