Visual Testing with Playwright: The Complete Tutorial
Source: Dev.to
Since version 1.22, Microsoft’s Playwright includes a native visual testing feature: the toHaveScreenshot() method. It captures screenshots and automatically compares them to reference images, with no external plugin needed. This is a strong option for development teams that want to add visual testing to their existing stack. The tutorial covers installation, configuration, best practices, and CI/CD integration.
Installation and first test
Setup is quick with an existing Node.js project:
npm install -D @playwright/test
npx playwright install
Create your first visual test in tests/visual.spec.ts:
import { test, expect } from '@playwright/test';
test('homepage visual test', async ({ page }) => {
await page.goto('https://your-site.com');
await expect(page).toHaveScreenshot('homepage.png');
});
The first run generates the baseline. Subsequent runs compare against it.
Configuring tolerance
By default, Playwright flags any single‑pixel difference. In practice, configure thresholds to avoid false positives:
// playwright.config.ts
export default defineConfig({
expect: {
toHaveScreenshot: {
maxDiffPixelRatio: 0.01,
animations: 'disabled',
scale: 'device',
},
},
});
Handling dynamic content
Three common solutions:
- Mask dynamic zones – use the
maskoption to ignore changing parts of the page. - Replace content via
page.evaluate()– inject deterministic data before taking the screenshot. - Hide with injected CSS – add a style block that hides or stabilizes animated elements.
Each approach balances reliability and maintenance effort.
Stabilizing tests
- Wait for network idle, font loading, and critical element visibility before capturing.
- Disable animations globally in the Playwright config (as shown above).
- Use explicit waits or
page.waitForLoadState('networkidle')when needed.
Multi‑resolution testing
Leverage Playwright projects to run the same test suite across different viewports and devices, each with its own baseline:
// playwright.config.ts
export default defineConfig({
projects: [
{
name: 'Desktop',
use: { viewport: { width: 1920, height: 1080 } },
},
{
name: 'Tablet',
use: { viewport: { width: 768, height: 1024 } },
},
{
name: 'Mobile',
use: { device: 'iPhone 13' },
},
],
});
CI/CD integration
GitHub Actions (or any CI system) can run visual tests automatically. When a test fails, Playwright generates three images:
- Baseline – the stored reference screenshot.
- Actual – the newly captured screenshot.
- Diff – a red‑highlighted image showing pixel differences.
The HTML report displays these side‑by‑side, making it easy to review failures in the pipeline.
Limitations
- Requires TypeScript/JavaScript knowledge.
- No built‑in review dashboard; you rely on the generated HTML report.
- Pixel comparison is basic—anti‑aliasing and font‑rendering differences between browsers can cause noise.
- Managing baselines for many tests across multiple browsers can lead to a large number of files (e.g., 200 + tests × 3 browsers = 600 + baseline images).
For teams that prefer a no‑code approach, consider Delta‑QA, which offers visual regression testing without writing code, managing baselines, or dealing with false positives.
FAQ
Is Playwright free for visual testing?
Yes. toHaveScreenshot() is built into Playwright, which is open‑source and free to use.
Playwright or Cypress for visual testing?
Playwright provides native visual testing, while Cypress requires an external plugin. Playwright also supports three browser engines (Chromium, Firefox, WebKit) versus Cypress’s single‑engine focus, making Playwright the stronger choice for visual testing.
Can you use Playwright and Delta‑QA together?
Absolutely. Use Playwright for complex developer‑focused tests and Delta‑QA for routine visual checks performed by QA teams.