Скриншоты, сравнение с эталоном, snapshot testing, настройка порогов
Snapshot testing в Playwright позволяет автоматически детектировать любые визуальные изменения. Это мощный инструмент для предотвращения регрессий дизайна.
Базовый скриншот всей страницы:
# Сохранить в файл
await page.screenshot(path='screenshot.png')
# Получить bytes для дальнейшей обработки
screenshot_bytes = await page.screenshot()
# Только видимая область viewport (без прокрутки)
await page.screenshot(path='visible.png', full_page=False)full_page=True (по умолчанию) снимает всю страницу, включая область за пределами экрана.
# Скриншот одного элемента
logo = page.locator('.logo')
await logo.screenshot(path='logo.png')
# Скриншот кнопки
await page.get_by_role('button', name='Сохранить').screenshot(path='button.png')Playwright автоматически обрезает изображение по границам элемента.
Основной инструмент визуального тестирования:
from playwright.sync_api import expect
def test_homepage_snapshot(page):
page.goto('/')
expect(page).to_have_screenshot('homepage.png')При первом запуске эталонного файла нет — тест упадёт. Запустите с --update-snapshots для создания эталона:
pytest test_visual.py --update-snapshotsЭталон сохранится в test-snapshots/homepage-<browser>.png. При последующих запусках скриншот сравнивается с эталоном.
Anti-aliasing и рендеринг шрифтов могут давать небольшие различия:
# Допустить до 100 отличающихся пикселей
expect(page).to_have_screenshot('page.png', max_diff_pixels=100)
# Полное совпадение (по умолчанию)
expect(page).to_have_screenshot('page.png')Даты, анимации, аватары — элементы, которые меняются и не должны ломать тест:
expect(page).to_have_screenshot(
'dashboard.png',
mask=[
page.locator('.timestamp'), # Динамическая дата
page.locator('.avatar'), # Аватар пользователя
page.locator('.animation'), # CSS-анимация
],
)Playwright закрашивает замаскированные элементы сплошным розовым цветом перед сравнением.
element = page.locator('.product-card')
expect(element).to_have_screenshot('product-card.png')Это проверяет визуальную целостность отдельного компонента.
Иногда нужно сделать скриншот до и после действия:
def test_button_hover(page):
page.goto('/components')
button = page.get_by_role('button', name='Hover me')
# Скриншот до наведения
expect(button).to_have_screenshot('button-default.png')
# Наведение
button.hover()
# Скриншот после наведения
expect(button).to_have_screenshot('button-hover.png')# Полная страница с прокруткой (по умолчанию)
await page.screenshot(path='full.png', full_page=True)
# С фиксированным viewport — скриншот только видимой области
await page.screenshot(path='viewport.png', full_page=False)# PNG (по умолчанию) — без потерь, для сравнения
await page.screenshot(path='screenshot.png')
# JPEG — сжатие с потерями, меньше размер
await page.screenshot(path='screenshot.jpg', quality=80)Важно: для snapshot testing всегда используйте PNG. JPEG с потерями создаёт артефакты, которые ломают пиксельное сравнение.
После легитимного изменения дизайна:
# Обновить все эталоны
pytest test_visual.py --update-snapshots
# Обновить один конкретный
pytest test_visual.py::test_homepage_snapshot --update-snapshotsОбновлённые эталоны нужно закоммитить в репозиторий.
Скриншоты на macOS и Linux будут отличаться из-за рендеринга шрифтов. Решение:
# Генерировать эталоны в CI (Linux) — только там проверять
import platform
@pytest.mark.skipif(platform.system() == 'Darwin', reason='Шрифты отличаются на macOS')
def test_snapshot_linux(page):
page.goto('/')
expect(page).to_have_screenshot('homepage-linux.png')Или используйте max_diff_pixels для допуска небольших различий.
❌ JPEG для snapshot testing. Сжатие создаёт артефакты — пиксельное сравнение будет падать. Используйте PNG.
❌ Скриншоты с динамическим контентом. Даты, время, рандомные данные — каждый раз новый скриншот. Маскируйте такие элементы.
❌ Скриншоты во время анимации. Если CSS-transition ещё не завершился, скриншот будет отличаться. Дождитесь окончания: expect(locator).to_be_visible() перед скриншотом.
✅ Правильный подход: PNG, маскирование динамических элементов, ожидание завершения анимаций, генерация эталонов на одной платформе.
https://example.com и скриншот только элемента <h1>.--update-snapshots и проверьте, что тест проходит.Изучите тестирование мобильных устройств, чтобы эмулировать iPhone, Android и планшеты.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.