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-тестов уже сегодня — получите консультацию по вашему проекту. Свяжитесь с нами для оценки — мы подберём оптимальный инструмент и составим план внедрения.







