Visual Regression Testing
Visual Regression Testing — автоматическое обнаружение непреднамеренных визуальных изменений в UI путём попиксельного сравнения скриншотов с эталонными снимками.
Зачем нужно
CSS-изменения легко ломают другие компоненты. Unit и integration тесты не замечают визуальных регрессий — неправильный отступ, перекрытый текст, сломанный layout. Visual regression testing автоматически ловит эти изменения до того, как они попадут в production.
Где используется
- Design system и UI-библиотеки компонентов
- Критичные страницы: главная, checkout, формы авторизации
- После обновления CSS-фреймворка или глобальных стилей
- При рефакторинге компонентов
Основной контент
Playwright — встроенные visual comparisons
// tests/visual/button.spec.ts
import { test, expect } from '@playwright/test';
test('кнопка выглядит корректно', async ({ page }) => {
await page.goto('/components/button');
// Скриншот всей страницы
await expect(page).toHaveScreenshot('button-page.png');
// Скриншот конкретного элемента
const button = page.getByRole('button', { name: 'Primary' });
await expect(button).toHaveScreenshot('primary-button.png');
});
test('кнопка в состоянии hover', async ({ page }) => {
await page.goto('/components/button');
const button = page.getByRole('button', { name: 'Primary' });
await button.hover;
await expect(button).toHaveScreenshot('primary-button-hover.png');
});
Обновление baseline скриншотов
# Первый запуск — создаёт эталонные скриншоты
npx playwright test --update-snapshots
# Последующие запуски — сравнивают с эталоном
npx playwright test
Настройка порога различий
// playwright.config.ts
export default defineConfig({
expect: {
toHaveScreenshot: {
maxDiffPixels: 100, // допустимое кол-во отличающихся пикселей
threshold: 0.2, // допустимый % различий на пиксель (0-1)
animations: 'disabled', // отключаем анимации для стабильности
},
},
});
Storybook + Chromatic
npm install --save-dev chromatic
npx chromatic --project-token=YOUR_TOKEN
Chromatic автоматически делает скриншот каждой Storybook story и уведомляет при изменениях. В PR показывает visual diff с подсветкой изменений.
Jest + jest-image-snapshot
import { toMatchImageSnapshot } from 'jest-image-snapshot';
import puppeteer from 'puppeteer';
expect.extend({ toMatchImageSnapshot });
test('страница выглядит правильно', async () => {
const browser = await puppeteer.launch;
const page = await browser.newPage;
await page.goto('http://localhost:3000');
const screenshot = await page.screenshot;
expect(screenshot).toMatchImageSnapshot({
failureThreshold: 0.01,
failureThresholdType: 'percent',
});
await browser.close();
});
Папка со скриншотами
tests/
visual/
button.spec.ts
button.spec.ts-snapshots/
primary-button-chromium-linux.png ← baseline
primary-button-hover-chromium-linux.png
Частые ошибки
- Разные ОС/браузеры дают разные скриншоты — рендеринг шрифтов и antialiasing отличаются; запускай visual tests всегда на одном окружении (Docker в CI)
- Скриншот с анимацией — CSS-анимация делает скриншоты нестабильными; отключай через
animations: 'disabled'или CSS* { animation: none } - Commit baseline без проверки — при
--update-snapshotsв CI автоматически принимаются все изменения; требуй ручного апрува diff в PR - Слишком жёсткий threshold — 1 разный пиксель = падение; начинай с разумного порога и ужесточай постепенно
Связанные темы
- _MOC Тестирование
- Jest -- snapshot тесты
- E2E тестирование
- Playwright -- обзор
- Cypress -- установка и основы