How to Improve Cypress Test Coverage with Visual Testing
Use code coverage, UI Coverage, and visual regression together to find untested logic, missed interactions, and visual regressions in Cypress.
To improve Cypress test coverage with visual testing, combine three checks that answer different questions: code coverage shows which source lines, functions, and branches ran; Cypress UI Coverage shows which interactive elements tests exercised; and visual regression testing compares rendered screenshots with approved baselines. Use functional assertions to reach a meaningful, stable UI state before capturing it. Add accessibility scans when you need to check standards such as text contrast. A screenshot alone does not measure code or interaction coverage, and Cypress captures screenshots but does not compare them by itself.
1. Understand the three kinds of coverage
| Method | What it tells you | What it does not tell you |
|---|---|---|
| Code coverage | Which instrumented source statements, functions, and branches ran during tests. | Whether every important UI control was exercised or whether the rendered page looks right. |
| Cypress UI Coverage | Which interactive UI elements tests touched or missed, based on recorded Test Replay data. | Whether unvisited source branches ran or whether pixels match a baseline. |
| Visual regression | Whether a rendered page or element differs from an approved screenshot baseline. | Whether the underlying logic or accessibility standards are correct. |
| Accessibility scanning | Whether evaluated properties meet defined accessibility rules, such as text contrast requirements. | Whether the page is pixel-identical to its prior appearance. |
Cypress describes code coverage and UI Coverage as complementary. A high code coverage percentage can coexist with controls no test has used; a visual diff can catch an unexpected layout change without showing which source branch caused it. Treat each report as a separate signal and prioritize gaps by user and product risk.
2. Add code coverage to Cypress
Code coverage works by instrumenting application code with counters. Tests run the instrumented application, and a coverage collector reports which statements, functions, and branches executed. Cypress points to the @cypress/code-coverage plugin for end-to-end collection; its current installation instructions should be followed because setup details may change. The plugin can use nyc to produce a static HTML report.
- Instrument the application code used by the Cypress test build.
- Install and configure
@cypress/code-coverageusing its current documentation, including the support-file setup required by your project. - Run the Cypress tests against the instrumented application and collect the coverage data.
- Generate a report, such as an HTML report through
nyc, and inspect uncovered statements, functions, and branches. - Add tests for meaningful gaps: important conditional paths, validation failures, permissions, empty states, and error handling.
Do not optimize only for the aggregate percentage. A missed branch in a payment failure path can matter more than several uncovered lines in a low-risk display helper. Coverage identifies where execution did not reach; the team still decides whether that code needs a test.
3. Map missed interactions with Cypress UI Coverage
Cypress UI Coverage reports interactive elements that tests exercised or missed. Cypress documents that it needs no separate instrumentation: reports are generated in Cypress Cloud from Test Replay data that recorded runs already capture. It is a Cypress Cloud feature, not a local screenshot diff.
The documented prerequisites are:
- A Cypress Cloud project with recorded test runs.
- Test Replay enabled.
- Cypress version 13 or later.
- UI Coverage enabled for the organization.
Cypress labels UI Coverage a premium solution. Check the current Cypress documentation and account settings for availability and setup details. Once enabled, use the uncovered-control report to find interactions your tests never tried: secondary navigation, modal dismissal, sorting, pagination, disabled states, and form controls. Then decide which interactions merit explicit functional tests and which are intentionally out of scope.
4. Add visual regression checks to Cypress
Cypress provides cy.screenshot() to capture the current page or a selected element. It does not perform image comparison itself. For regression testing, connect screenshot capture to a visual testing plugin or integration that compares the new image with a previously approved baseline and presents differences for review. Cypress describes both open-source local or CI comparison plugins and hosted integrations, including Sauce Labs Visual and SmartBear VisualTest; it also links to Chromatic’s Cypress documentation. The research does not establish a current apples-to-apples price or performance comparison, so choose based on workflow and verified current terms.
A Cypress test should first drive the application into a deliberate state, assert that the expected content is present, and only then capture. The following is runnable Cypress test code for capture; by itself, it saves a screenshot and does not compare it with a baseline:
describe('account settings visual state', () => {
it('captures the saved settings state', () => {
cy.visit('/settings');
cy.get('[data-cy=email]').clear().type('qa@example.test');
cy.get('[data-cy=save]').click();
cy.contains('Settings saved').should('be.visible');
// Cypress captures the current page; add a visual comparison
// integration to compare this image against an approved baseline.
cy.screenshot('settings-saved');
});
});
Use the comparison tool’s current Cypress integration instructions to connect capture and baseline review. Avoid presenting cy.screenshot() as a complete visual regression setup: image comparison and baseline management come from the chosen integration.
Choose the capture scope
- Whole page: useful for page-level layout, missing sections, and broad visual shifts. Long pages can be more sensitive to content and timing variation.
- Specific element: useful for a component with a defined visual contract, such as a pricing card, navigation menu, or dialog. Keep the selector stable and verify the element is visible before capture.
Snapshot meaningful states rather than every possible state. Typical high-value states include initial load, a successful form submission, validation errors, empty results, an open dialog, and a responsive breakpoint relevant to your users.
5. Make screenshots deterministic
A diff is useful only when unrelated rendering variation is controlled. Keep test data and application state repeatable, wait for the intended page state, and make the rendering environment consistent across baseline creation and later runs.
- Use fixed fixtures or seeded test data so names, counts, dates, and results do not drift.
- Assert the expected state with Cypress commands before taking a screenshot. Prefer a meaningful assertion over an arbitrary delay.
- If an animation or asynchronous update is part of the state, wait for it to finish or disable it through the visual test setup where appropriate.
- Make fonts available and stable before capture; font substitution can shift line breaks and layout.
- Keep browser, viewport, device scale, and operating environment consistent with the baseline workflow.
- Hide or stabilize genuinely dynamic values such as timestamps, rotating content, or randomized identifiers when they are outside the test’s purpose.
- When a diff appears, inspect it before accepting a new baseline. Approve only changes that are intentional.
Do not hide broad regions simply to make a diff pass: doing so can conceal the regressions the test is meant to reveal. Keep any masking or ignored-region configuration narrow and explain why the content is variable.
6. Use all reports to choose the next test
- Start with application risk: identify critical journeys and failure cases.
- Check code coverage for unexecuted logic on those paths.
- Check UI Coverage, if configured, for important controls no test exercised.
- Use visual comparisons to catch unintended rendering changes in representative states.
- Add accessibility scans when standards-based checks are required; a pixel comparison does not determine whether text contrast meets a standard.
- After fixing a gap, run the relevant tests and review both the functional assertions and visual changes.
This workflow gives each technique a clear job. Code coverage directs attention to unexecuted logic, UI Coverage highlights interaction gaps, visual testing catches changed appearance, and accessibility scans evaluate rule-based concerns.
7. Troubleshooting common problems
| Symptom | Likely cause | Fix |
|---|---|---|
| No code coverage report or an empty report | The tested application was not instrumented, the collector was not configured for the test run, or coverage data was not emitted. | Confirm instrumentation in the Cypress test build and follow the current @cypress/code-coverage setup for the support file and application server. Verify the run produces coverage data before generating a report. |
| UI Coverage is unavailable | A documented prerequisite is missing: Cloud-recorded runs, Test Replay, Cypress 13+, or organization enablement. | Check each prerequisite and the current Cypress Cloud organization settings. Confirm your plan and feature access with Cypress. |
| A screenshot exists but no diff appears | cy.screenshot() only captures; Cypress does not compare the image itself. |
Install and configure a visual comparison integration, then connect its baseline and review workflow. |
| Many pixels differ on every run | Data, fonts, timing, viewport, browser, or rendering environment changes between runs. | Stabilize fixtures and environment, wait for the intended state, and isolate truly dynamic regions narrowly. |
| A screenshot captures a loading or intermediate state | The test took the image before the application finished rendering. | Assert the expected content or state before capture. Wait for a meaningful condition instead of relying on a fixed sleep alone. |
| A visual test fails after an intentional design change | The baseline still represents the prior, approved appearance. | Review the diff in context and update the baseline through the integration’s review process only after confirming the change is intended. |
| Visual tests pass while a contrast issue remains | Pixel comparison checks image change, not conformance to accessibility standards. | Add accessibility scanning for standards-based checks such as contrast. |
| Coverage percentage rises but meaningful gaps remain | The percentage is aggregated and does not encode business importance or prove that each UI interaction was tested. | Review uncovered branches and controls against critical journeys, error cases, and user impact. |
8. Performance, reliability, and cost considerations
Visual testing adds screenshot capture, comparison, and review work to a test workflow. The sources here do not provide general performance benchmarks, so measure the effect in your own CI pipeline. Begin with a focused set of high-value states and expand when the additional signal justifies the capture and review effort.
- Runtime: wait for actual state readiness, avoid redundant snapshots, and capture only the scope that answers the regression question.
- Reliability: deterministic data and consistent rendering reduce noise. Keep functional assertions so a screenshot cannot silently capture the wrong state.
- Review effort: broad snapshots and unstable content can produce noisy diffs. Prioritize stable, meaningful states and inspect changed pixels before baseline approval.
- Cost: Cypress UI Coverage is identified as premium; visual integration prices and service limits vary and should be checked with vendors. The research does not support a price ranking.
- Coverage interpretation: instrumentation, interaction mapping, screenshots, and accessibility scans measure different things. Do not substitute one number or pass result for the others.
9. Or skip the browser setup
For an image capture outside your Cypress-run browser workflow, ScreenshotNeo is a website screenshot API and MCP server. It can return a PNG, JPEG, WebP, or PDF from one GET request. Use your own browser-driven Cypress tests for interactive application behavior and visual assertions; this API call is useful when you need a clean screenshot of a URL without maintaining capture-browser setup.
See the ScreenshotNeo API documentation. This cURL example saves a WebP capture:
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));
ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. See all options and configuration in the docs, then sign up for 1,000 free screenshots a month, with no card required.
10. Frequently asked questions
Does visual testing increase Cypress code coverage?
Not by itself. A visual snapshot can run in a test, but code coverage comes from instrumented application execution and measures source code reached.
Can a screenshot prove a control works?
No. It shows rendered appearance at capture time. Use Cypress interactions and assertions to verify behavior, and use UI Coverage to identify controls that recorded tests did or did not touch.
Should every Cypress test have a screenshot assertion?
No. Select representative, stable states tied to meaningful visual regression risks. Excess snapshots can add review work without adding useful coverage.
Can visual regression testing replace accessibility testing?
No. Screenshot comparison detects image differences; accessibility scans evaluate defined properties against rules and standards.
When should I update a visual baseline?
After reviewing a reported difference and confirming that the new appearance is intentional. A passing workflow depends on deliberate baseline approval, not automatic acceptance of every changed image.


