Screenshots and visual regression testing

Learn how to take some pictures and implement visual regression tests.

Even though Playwright provides stellar tools to debug your tests, sometimes you might want to take screenshots while running your headless tests.

Page screenshots

import { test, expect } from "@playwright/test";

test("get started link", async ({ page }) => {
  await page.goto("https://playwright.dev/");

  // take a page screenshot
  await page.screenshot({ path: "./home.png" });
});

Use page.screenshot() to capture the state of the page.

Todo

Locator screenshots

If you're only interested in a particular DOM element, locators provide screenshots, too.

import { test, expect } from "@playwright/test";

test("get started link", async ({ page }) => {
  await page.goto("https://playwright.dev/");

  // take a screenshot of a particular element
  await page
    .getByRole("link", { name: "Docs" })
    .screenshot({ path: "./docs.png" });
Todo

How to leverage browser names in your screenshot path

If you're running parallel tests with multiple browsers, including the browserName in the screenshot path avoids that all the screenshots overwrite each other.

test("get started link", async ({ page, browserName }) => {
  await page.goto("https://playwright.dev/");
  await page
    .getByRole("link", { name: "Docs" })
    .screenshot({ path: `./docs-${browserName}.png` });
});
Note

The page, browserName and other test variables are called test fixtures. Playwright provides many fixtures for different use cases and we'll look at them later.

Todo

Visual regression snapshots

Even though screenshots are handy to evaluate what your tests are doing you can level it up a notch and implement visual regression testing with a single assertion — toHaveScreenshot().

test("get started link", async ({ page, browserName }) => {
  await page.goto("https://playwright.dev/");
  // visual regression works on a page level...
  await expect(page).toHaveScreenshot("home.png");
  // but also on a locator level
  await expect(page.getByRole("link", { name: "Docs" })).toHaveScreenshot(
    "docs.png",
  );
});

toHaveScreenshot() will create page and component screenshots next to your test files and perform visual regression tests in future runs. Additionally, it automatically captures the browser and OS in use to take the screenshot ([test-name]-[browser]-[os].png). 💪

Note that when you run a test with visual regression for the first time, it'll fail becomes there's nothing to compare. 😅

Note

Playwright by default disables animations and transitions when taking screenshots to avoid flakiness because of moving elements.

Todo

Screenshot configuration

screenshot() and toHaveScreenshot() provide multiple configuration options:

  • mask
  • maxDiffRatio
  • scale
  • ...

Familialize yourself with all these options to get the most out of your screenshots!

Todo

Screenshots as test attachments

If trace files and the UI mode don't provide you essential info, you can also attach images (and other media) to the test results with testInfo.attach().

test("basic test", async ({ page }, testInfo) => {
  await page.goto("https://playwright.dev");
  const screenshot = await page.screenshot();
  await testInfo.attach("screenshot", {
    body: screenshot,
    contentType: "image/png",
  });
});
Note

Test attachments can be very valuable when you tests are dealing with file up and downloads.

Todo

Solution

💡 If you're stuck, find a working example on GitHub.