Snapshot-тестирование — это автоматический контроль того, что UI не изменился незапланированно. Разработчик правит отступ в одном компоненте, забывает про экран настроек, где тот же компонент используется с другими пропсами — и через неделю в продакшене обнаруживается съехавшая вёрстка. Snapshot-тест поймал бы это за секунды. Мы внедряем такие тесты под ключ: настраиваем инструмент, пишем тесты для ключевых компонентов и интегрируем проверку в CI. Это экономит часы ручных проверок и предотвращает регрессии.
Почему snapshot-тесты критичны для мобильного приложения?
Без автоматической верификации UI любое изменение стилей или компонентов может привести к визуальным багам, которые не ловятся модульными тестами. Ручной просмотр экранов перед релизом — медленный и ненадёжный. Snapshot-тесты решают проблему: один запуск — 100% проверка всех экранов.
Суть проста: при первом запуске тест сохраняет эталонное изображение или сериализованное дерево компонентов. При каждом следующем запуске сравнивает с эталоном. Расхождение = падающий тест.
Сравнение инструментов snapshot-тестирования
| Платформа | Инструмент | Среднее время теста | Поддержка Compose/SwiftUI |
|---|---|---|---|
| iOS | swift-snapshot-testing | 1–3 сек | SwiftUI (через UIView) |
| Android | Paparazzi | 200–500 мс | Jetpack Compose |
| Flutter | Golden Tests | 0.5–1 сек | Flutter Widget |
Paparazzi в 20 раз быстрее, чем screenshot-тесты с эмулятором: 200 мс против 6 секунд на тест. Для библиотеки на 200 компонентов разница 30 минут против 3 минут.
iOS: iOSSnapshotTestCase
На iOS snapshot-тесты строятся на pointfreeco/swift-snapshot-testing (бывший FBSnapshotTestCase). Это наиболее зрелое решение:
import SnapshotTesting class ProfileViewControllerTests: XCTestCase { func testProfileScreen() { let vc = ProfileViewController(user: .mock) assertSnapshot(of: vc, as: .image(on: .iPhone13Pro)) } func testProfileScreenDarkMode() { let vc = ProfileViewController(user: .mock) assertSnapshot(of: vc, as: .image(on: .iPhone13Pro(.landscape), traits: .init(userInterfaceStyle: .dark))) } } assertSnapshot при первом запуске создаёт файл __Snapshots__/ProfileViewControllerTests/testProfileScreen.1.png. При следующих — сравнивает пиксель за пикселем. Порог — 0, любое отличие = fail.
Поддерживаемые стратегии снимка: .image (скриншот), .recursiveDescription (текстовое дерево view), .dump (структура). Для компонент-библиотек .image — основная.
Проблема с шрифтами в CI
Рендеринг текста на симуляторе может отличаться от рендеринга на CI-машине из-за разных версий системных шрифтов. Решение — фиксировать симулятор (iPhone 15, iOS 17.4) и использовать одну и ту же версию Xcode. В fastlane через xcversion:
xcversion(version: "~> 15.3") Android: Paparazzi
Для Android лучший инструмент — Paparazzi от Square. Он не требует эмулятора: рендерит View через LayoutInflater в JVM-окружении, используя layoutlib (тот же движок, что и Android Studio Preview).
class ButtonSnapshotTest { @get:Rule val paparazzi = Paparazzi( deviceConfig = DeviceConfig.PIXEL_6, theme = "Theme.App" ) @Test fun primaryButton() { paparazzi.snapshot { PrimaryButton( text = "Сохранить", onClick = {} ) } } } Запуск: ./gradlew recordPaparazziDebug (запись эталонов) и ./gradlew verifyPaparazziDebug (проверка).
Paparazzi поддерживает Jetpack Compose с paparazzi.snapshot { ComposableFunction() } — та же механика.
Flutter: Golden Tests
В Flutter snapshot-тесты называются Golden Tests и являются частью flutter_test:
testWidgets('CustomCard golden', (tester) async { await tester.pumpWidget( MaterialApp(home: CustomCard(title: 'Test', subtitle: 'Subtitle')), ); await expectLater( find.byType(CustomCard), matchesGoldenFile('goldens/custom_card.png'), ); }); Обновление эталонов: flutter test --update-goldens.
Платформо-зависимость golden-файлов — известная проблема. macOS рендерит шрифт иначе, чем Linux (CI). Решение: хранить golden-файлы, сгенерированные на CI (Linux), а локально разработчики используют flutter test --update-goldens только на той же ОС. Либо пакет golden_toolkit с loadAppFonts(), который нивелирует часть различий.
Как snapshot-тесты интегрируются в CI?
Мы настраиваем CI-пайплайн так, чтобы в нём выполнялась только верификация (verify), а запись эталонов происходила локально. Это гарантирует, что изменения UI не проскользнут незамеченными.
Типичные причины расхождений на CI
- Разные версии шрифтов
- Разный рендеринг на симуляторе и CI-машине
- Разрешение экрана и масштаб
- Версии Xcode и SDK
Рекомендуется фиксировать окружение и запускать запись эталонов на той же среде, где будет CI.
Пример из нашей практики
Для одного из проектов (клиент — fintech-сервис) мы внедрили snapshot-тесты на Flutter. Компонентная библиотека содержала 120 виджетов. После настройки golden-тестов время регрессионного тестирования UI сократилось с 2 часов ручного просмотра до 3 минут автоматической проверки. Все эталонные снимки хранятся в репозитории и обновляются только осознанно.
Что входит в работу
- Анализ текущей UI-архитектуры и выбор инструмента
- Настройка инструмента snapshot-тестирования (iOS/Android/Flutter)
- Написание тестов для ключевых экранов и компонентов (10–30 тестов)
- Интеграция в CI (GitHub Actions, GitLab CI или Bitrise)
- Документация по работе со снимками и процессу обновления
- Обучение команды (1–2 часа)
Управление базовыми снимками в git
Эталонные снимки хранятся в репозитории. Несколько правил:
-
__Snapshots__/,src/test/snapshots/,test/goldens/— добавляем в.gitattributesкак бинарные:*.png binary - Pull Request с изменением UI должен включать обновлённые снимки:
git add test/goldens/ && git commit -m "update snapshots" - В CI запускаем только проверку (
verify), не запись (record). Запись — только локально или через специальный workflow
Если CI падает из-за расхождения снимков — это не ошибка тестов, это сигнал о незапланированном изменении UI. Хорошо.
Сроки и стоимость
2–3 дня — настройка инструмента + написание snapshot-тестов для ключевых компонентов. Полное покрытие компонентной библиотеки (50+ компонентов) — оцениваем отдельно. Стоимость рассчитывается индивидуально. У нас 5 лет опыта в мобильной разработке и более 30 проектов с автотестами — гарантируем качество и соблюдение сроков.
Закажите внедрение snapshot-тестов уже сегодня — получите консультацию по вашему проекту. Свяжитесь с нами для оценки — мы подберём оптимальный инструмент и составим план внедрения.







