Snapshot тесты

Snapshot-тестирование в контексте WebGL-рендеринга применяется для фиксации визуального состояния сцены или структурного представления графического слоя в конкретный момент времени. В экосистеме Deck.gl этот подход используется для контроля регрессий при изменениях в слоях, вычислении координат, трансформациях и логике отрисовки.

Ключевая особенность WebGL-сцен — высокая чувствительность к окружению выполнения: драйверы GPU, различия в плавающей точке, порядок операций рендеринга. Snapshot-тестирование в таких условиях требует строгой стабилизации входных данных и окружения.

Формы snapshot-тестирования

Текстовые snapshot’ы структуры слоёв

Первый уровень snapshot-тестирования связан не с пикселями, а с сериализацией состояния слоя. В тестах фиксируются:

  • параметры viewState
  • конфигурация камер
  • список слоёв и их свойства
  • вычисленные атрибуты (positions, colors, elevations)
  • результирующий props после композиции

Такой подход позволяет отслеживать логические изменения в графе рендеринга без необходимости работы с изображениями.

Пример структуры:

{
  viewState: {
    longitude: 37.62,
    latitude: 55.75,
    zoom: 12,
    pitch: 45,
    bearing: 0
  },
  layers: [
    {
      id: "hex-layer",
      type: "HexagonLayer",
      opacity: 0.8
    }
  ]
}

Snapshot фиксирует не визуальный результат, а декларативное описание сцены.

Image snapshot тестирование WebGL

Более строгая форма контроля — сравнение итогового изображения. В этом случае рендеринг выполняется в headless-окружении, после чего полученный буфер кадра сравнивается с эталонным изображением.

Часто используется связка:

  • Jest
  • headless-gl
  • @deck.gl/test-utils
  • jest-image-snapshot

Рендер сцены выполняется в offscreen canvas, результат сериализуется в PNG или raw buffer.

Принцип работы image snapshot

  1. Инициализация WebGL контекста без браузера
  2. Создание экземпляра Deck с фиксированным viewState
  3. Отрисовка слоя
  4. Считывание пикселей через gl.readPixels
  5. Сравнение с эталонным изображением

Проблема недетерминированности

Snapshot-тестирование в WebGL сталкивается с рядом факторов нестабильности:

  • различия GPU (floating-point precision)
  • порядок выполнения шейдеров
  • асинхронная загрузка данных
  • динамическое освещение и анимации
  • тайлы и внешние источники данных

Даже минимальные изменения могут привести к pixel diff, который формально считается ошибкой snapshot.

Методы стабилизации рендеринга

Фиксация состояния камеры

Ключевым фактором детерминированности является viewState. Любая вариативность камеры приводит к изменению проекции и, как следствие, изображения.

Фиксируются параметры:

  • zoom
  • pitch
  • bearing
  • longitude / latitude

Отключение анимаций и интерполяций

Анимационные переходы создают промежуточные состояния сцены. Для snapshot-тестов используется:

  • transitionDuration: 0
  • отключение easing-функций
  • фиксация времени через mock timers

Стабилизация данных

Данные должны быть:

  • отсортированы
  • нормализованы
  • лишены случайных значений

Пример устранения случайности:

const data = rawData
  .map(d => ({ ...d }))
  .sort((a, b) => a.id - b.id);

Snapshot тестирование слоёв Deck.gl

В Deck.gl каждый слой представляет собой изолированную единицу рендеринга. Snapshot-тестирование может применяться на уровне:

  • Layer props
  • AttributeManager состояния
  • shader uniforms
  • итогового framebuffer

При тестировании слоя важно учитывать жизненный цикл:

  1. initialization
  2. attribute update
  3. draw call
  4. cleanup

Любое изменение в одном из этапов отражается в snapshot.

Использование test-utils

Пакет @deck.gl/test-utils предоставляет утилиты для:

  • создания тестового Deck экземпляра
  • симуляции WebGL контекста
  • захвата изображений
  • синхронного рендера сцены

Типовой сценарий:

import { testRenderLayers } from '@deck.gl/test-utils';

test('HexagonLayer snapshot', async () => {
  const image = await testRenderLayers({
    layers: [hexLayer],
    viewState
  });

  expect(image).toMatchImageSnapshot();
});

CI-интеграция snapshot тестов

Snapshot-тесты в WebGL часто запускаются в CI окружении с ограничениями GPU. Для этого используются:

  • software rasterizer (SwiftShader)
  • headless Chromium
  • виртуальные framebuffer реализации

Важный аспект — стабильность окружения:

  • фиксированная версия драйвера
  • одинаковые флаги WebGL
  • контроль разрешения canvas

Любое отклонение окружения приводит к массовым diff-ошибкам.

Диффы изображений

При расхождении snapshot’ов используются методы визуального сравнения:

  • pixel-by-pixel diff
  • threshold-based comparison
  • perceptual hashing (pHash)

В большинстве тестовых систем допускается небольшой порог различий:

  • 0.1%–1% пикселей
  • игнорирование альфа-канала
  • маскирование динамических областей

Тестирование с тайловыми слоями

Tile-based слои создают дополнительную сложность:

  • асинхронная загрузка данных
  • частичное обновление кадра
  • прогрессивный рендеринг

Для snapshot тестов применяется:

  • мокирование fetch-запросов
  • фиксация tile index
  • ожидание завершения загрузки слоя

Частые причины нестабильных snapshot’ов

  • использование Math.random в атрибутах
  • отсутствие сортировки геоданных
  • различия precision float32/float64
  • WebGL extensions на разных GPU
  • незафиксированное время (Date.now)
  • асинхронные обновления состояния слоя

Архитектурные подходы к snapshot-тестированию

Snapshot тесты в Deck.gl обычно разделяются на уровни:

  • unit snapshot (слои)
  • integration snapshot (Deck instance)
  • regression snapshot (полные сцены)

Такое разделение позволяет локализовать изменения: от логики атрибутов до финального рендера.

Роль mock WebGL окружения

Для воспроизводимости используется:

  • mock canvas
  • shim WebGL context
  • фиксированные extensions
  • ограниченный feature set

Это снижает влияние аппаратных различий и делает snapshot сравнимым между машинами.

Управление обновлением snapshot’ов

Обновление эталонов происходит только при осознанных изменениях визуальной логики:

  • изменение shader логики
  • обновление цветовых схем
  • изменение геометрии слоя

Любое автоматическое обновление без анализа приводит к накоплению визуальных регрессий.