Connect your existing test commands to a CI workflow, run the fastest high-signal checks on each pull or merge request, and make the results visible to reviewers. Then add integration and focused end-to-end checks where they protect behavior that unit tests cannot, keeping slower suites for suitable pipeline stages or scheduled runs.
Plan the pipeline around the tests you already have
Before editing CI configuration, inventory your unit, integration, API, system, and end-to-end (E2E) tests. Record each suite’s command, required services and test data, approximate runtime, and the failures it is meant to catch. Reuse existing coverage rather than creating a second test at a higher level for the same behavior.
- Unit tests: Run small, fast checks of individual components early; they are generally easier to diagnose than full-stack failures.
- Integration tests: Check boundaries between components or services. Identify which databases, containers, or other dependencies the job must start.
- System and E2E tests: Reserve these for critical user journeys and cross-service behavior that lower-level tests cannot establish. They often need a more complete environment, so avoid duplicating unit or integration coverage.
GitLab’s testing guidance likewise recommends checking lower-level coverage before adding E2E tests and treating suite health as ongoing work. See GitLab’s E2E testing guidance and its testing strategy.
Use a staged flow, not a required template
A useful starting model is:
change event → build/setup → unit tests → integration tests → package or deploy to a test environment → focused smoke/E2E checks → reports and gate → deploy
This is a way to organize feedback, not a mandatory sequence. Combine or split jobs to fit the application’s architecture, runner capacity, and dependencies. Put quick, high-signal checks early so reviewers learn about common failures before slower work completes.
Choose what blocks what
Decide separately whether a check should block a merge, a deployment, or neither. A fast and reliable unit suite is a common early gate; a broad or expensive suite may be more appropriate on a schedule or at a later deployment boundary. A focused smoke test after deployment can check a critical path without requiring every broad test to run on every change. The right boundary depends on risk and runtime, not a universal stage recipe.
Connect the workflow to code changes
Start with pull-request or merge-request events so a proposed change gets a result during review. GitHub Actions can also run workflows on schedules and external events, and supports GitHub-hosted or self-hosted runners. GitLab documents feature-branch testing and pipeline jobs. Use the platform’s current configuration reference for exact event names and YAML syntax.
The exact workflow file and test command depend on your repository and framework. Add the same command developers already use locally, with the normal dependency installation and build steps, rather than guessing at a framework-specific command. Configure the test job to fail when the test process returns a genuine nonzero failure status, and publish a machine-readable report if the CI platform and test runner support it.
Add jobs in manageable layers
1. Run fast checks first
Set up the required runtime and dependencies, build the change if needed, and run unit or similarly fast tests. Confirm the job’s status appears on the pull or merge request so reviewers can use it. GitHub documents CI results in pull requests; GitLab documents test reports and artifacts in pipelines.
2. Provision integration dependencies explicitly
For integration tests, declare or start the database, service, or container dependencies the tests need. Keep setup isolated from other runs and make test data repeatable. Include teardown where appropriate so one job’s state cannot contaminate another. Jenkins’ testing guidance includes isolated setup and teardown patterns; its examples are platform guidance, not a requirement to use Jenkins.
Jenkins developer testing guidance
3. Add only the E2E checks that earn their runtime
Choose a small set of critical journeys or service boundaries that genuinely require the integrated or deployed environment. Make tests independent and repeatable where possible. If browser tests are part of the suite, keep them targeted and ensure their environment, test account, and data are available to the job. A full browser suite need not be a merge gate if its runtime or reliability makes that inappropriate; select a later stage or schedule deliberately.
4. Preserve evidence when a job fails
Publish test reports and retain useful logs and environment details, such as service output or deployment events. In its E2E pipeline examples, GitLab saves cluster events and pod logs and generates a report; the principle is broadly useful even if your CI system stores evidence differently. A bare red status is less useful than a failure report reviewers can inspect.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
GitLab test reports and testing documentation
Make test results useful to reviewers
Verify the workflow from a real change: the event triggers the expected jobs, successful tests show a passing result, and a deliberately failing test makes the appropriate job fail. Confirm reviewers can open the report and logs from the pull or merge request or its linked pipeline. Test reports should complement, not replace, a meaningful job exit status.
Rank #4
When deciding whether a test belongs in the pipeline, compare its feedback speed, the confidence it adds, runtime and runner cost, reproducibility, environment needs, and report quality. Also decide whether its result should block a merge, deployment, or neither. There is no single cross-vendor cost benchmark established here; actual cost depends on the platform, runner arrangement, and workload.
Keep the suite trustworthy over time
- Track job duration and investigate suites whose runtime grows enough to delay useful feedback.
- Fix flaky tests rather than allowing repeated nondeterministic failures to weaken confidence in CI.
- Remove redundant checks when a lower-level test already provides the needed coverage.
- Review quarantined tests and restore, repair, or remove them intentionally.
- Revisit gates as application risk, dependencies, or runner capacity changes.
GitLab’s internal testing strategy uses different suite depth and blocking rules across merge-request and deployment tiers. Treat that as one organization’s example, not a universal prescription.
Common problems and fixes
- The workflow never starts: Check that its trigger includes the event and branch conditions used by the repository, and verify the workflow file is in the location required by the platform.
- Tests pass locally but fail in CI: Compare runtime versions, installed dependencies, environment variables, services, and test data. Make job setup explicit and repeatable instead of relying on state present on a developer machine.
- Integration tests cannot connect to a dependency: Confirm the service is started in the job, its address and credentials match the test configuration, and the job waits for it to be ready before running tests.
- A failed job has no useful report: Configure report generation and artifact or test-report publication for the runner and platform; retain relevant logs and environment evidence.
- One flaky E2E test blocks unrelated work: Reproduce and repair the nondeterminism, isolate its dependencies, and reconsider whether it should gate a merge while it is unreliable.
- CI feedback is too slow: Move quick checks earlier, separate suites by purpose, and reserve broad or expensive coverage for a later stage or schedule when appropriate.
Or skip the browser setup
If your pipeline needs website screenshots as test evidence or for visual checks, you can capture a page with one request instead of setting up browser automation. For example, this cURL call saves a WebP shot of Stripe:
Free tools Windows power users keep installed
One-click scans. No signup required.
Best Value
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. ScreenshotNeo accepts cookie or consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides screenshot, page-info, and PDF capture tools for AI agents. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. See ScreenshotNeo for service details, then sign up for 1,000 free screenshots a month, with no card required.
Frequently Asked Questions
Should every test run on every pull request?
No. Run fast, reliable checks early; place broad or expensive suites on an appropriate later stage or schedule.
Do E2E tests replace unit and integration tests?
No. Use E2E tests for critical behavior that lower-level tests cannot establish, rather than repeating existing coverage.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

