Screenshot Test — автоматизированная проверка пользовательского интерфейса путём захвата и сравнения скриншотов экранов приложения с эталонными изображениями. В отличие от golden-тестов, screenshot-тесты выполняются на реальных устройствах или эмуляторах, захватывают полные экраны с навигацией, системными элементами и анимациями, и используют UI Automator (Android) или XCUITest (iOS) для взаимодействия с приложением. Подробнее — в документации Android UI Automator.
Главное
Screenshot Test — это end-to-end тестирование пользовательского интерфейса, при котором тест открывает экран приложения, выполняет действия (тапы, ввод текста, скролл) и делает скриншот полученного состояния. Скриншот сравнивается с эталоном (baseline), хранящимся в репозитории. Если скриншоты различаются — тест падает. Screenshot-тесты обнаруживают визуальные регрессии, которые не видны unit-тестам: неправильные отступы, наложение элементов, неверные цвета.
Зачем нужны screenshot-тесты, если есть golden-тесты — golden-тесты проверяют компоненты изолированно: одна кнопка, одна карточка, один текст. Screenshot-тесты проверяют целый экран в среде, максимально приближенной к продакшену: реальная навигация, реальные данные (или максимально реалистичные моки), реальные системные шрифты, реальный статус-бар. Только screenshot-тест покажет, что кнопка перекрывается другим элементом на реальном устройстве.
Бизнес-ценность — по данным Google (2023), визуальные баги составляют 15-25% всех багов мобильных приложений. Screenshot-тесты автоматизируют проверку визуального качества, которая раньше делалась вручную QA-инженерами. Один screenshot-тест заменяет 5-10 минут ручного тестирования одного экрана. Для приложения с 50 экранами экономия: 4-8 человеко-часов на один регрессионный прогон. Screenshot-тесты окупаются за 2-3 релизных цикла.
Golden-тесты быстрее и проще: рендер компонента в off-screen buffer занимает миллисекунды, не требует устройства, стабильны на CI. Screenshot-тесты реалистичнее: захватывают реальный экран с системными элементами, поддерживают анимации и навигацию, работают на реальных устройствах. Выбор зависит от цели: быстрая обратная связь для разработчика (golden) или максимальная реалистичность перед релизом (screenshot).
| Характеристика | Screenshot Test | Golden Test |
|---|---|---|
| Скорость | 2-30 секунд | 50-200 мс |
| Реалистичность | Максимальная (реальное устройство) | Ограниченная (off-screen) |
| Требует устройство | Да (эмулятор/физическое) | Нет (JVM, XCTest) |
| Анимации | Поддерживает | Не поддерживает |
| Навигация | Многошаговые сценарии | Один компонент |
| Flakiness | Высокая (сеть, тайминги) | Средняя (GPU, шрифты) |
| Параллельность | Device Farm (Firebase, AWS) | Многопоточный JVM/XCTest |
Golden + Screenshot — используйте golden-тесты для каждого UI-компонента в библиотеке компонентов (Design System). 80% визуальных регрессий ловятся на уровне компонентов. Screenshot-тесты — для критических пользовательских путей: онбординг, логин, платёжный флоу, корзина. 20% регрессий, связанных с интеграцией компонентов на реальном экране, ловятся только screenshot-тестами. В IT Sectr мы используем соотношение 80/20: 400 golden + 100 screenshot.
Когда screenshot-тест не нужен — если экран состоит из статического контента без интерактивности, golden-тест компонента даёт тот же уровень проверки за меньшую цену. Если экран изменяется динамически (лента, чат), screenshot-тест требует сложной настройки данных и времени ожидания. В таких случаях используйте screenshot для базового состояния (пустой список, загрузка) и golden для отдельных карточек в списке.
UI Automator — Android-фреймворк для кроссприложного UI-тестирования. Позволяет делать скриншоты через UiDevice.takeScreenshot(). В отличие от Espresso (работает внутри одного приложения), UI Automator может взаимодействовать с системными диалогами (разрешения, уведомления) и другими приложениями. Screenshot-тест на UI Automator: открыть приложение, дождаться загрузки, сделать скриншот, сравнить с эталоном.
class LoginScreenScreenshotTest {
@get:Rule
val rule = ComposeTestRule.createAndroidComposeRule<MainActivity>()
@Test
fun login_screen_default() {
val device = UiDevice.getInstance(
InstrumentationRegistry.getInstrumentation()
)
// Ждём загрузки экрана
IdlingRegistry.getInstance().waitForIdle()
// Делаем скриншот
val screenshot = device.takeScreenshot()
val golden = loadGolden("login_default.png")
// Сравниваем с эталоном
val diff = ImageComparator.compare(screenshot, golden)
assertTrue(diff.similarity > 0.98)
}
}
Firebase Test Lab — Google Cloud сервис для запуска инструментальных тестов на сотнях реальных устройств параллельно. Screenshot-тесты на Firebase Test Lab захватывают скриншоты на разных устройствах (Pixel 7, Galaxy S24, Xiaomi 14) и сравнивают с эталонами. Преимущество: один тест проверяет UI на 20 устройствах за 10-15 минут. Недостаток: стоимость ($1-5 за тест на 20 устройств). Firebase Test Lab интегрируется с CI через gcloud CLI или Gradle plugin.
Shot — библиотека для screenshot-тестирования на Android, облегчающая создание и сравнение скриншотов. Shot работает поверх Espresso и UI Automator, добавляя manage golden (создание, обновление, удаление), сравнение с threshold (пиксели или проценты) и генерацию HTML-отчёта. Shot подходит для проектов, которые хотят быстро внедрить screenshot-тестирование без написания своей инфраструктуры сравнения изображений.
XCUITest — фреймворк Apple для UI-тестирования iOS, iPadOS и tvOS приложений. Screenshot-тесты на XCUITest используют XCUIScreen.main.screenshot() для захвата экрана и XCAttachment для сохранения скриншота. XCUITest симулирует пользовательские действия: tap, swipe, typeText, и делает скриншоты после каждого шага. В Xcode 16+ добавлена встроенная поддержка сравнения скриншотов с эталонами через XCTAttachment.
final class LoginScreenScreenshotTests: XCTestCase {
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
app.launch()
}
func test_login_initial_state() {
let loginButton = app.buttons["login_button"]
XCTAssertTrue(loginButton.exists)
// Делаем скриншот
let screenshot = app.screenshot()
let attachment = XCTAttachment(screenshot: screenshot)
attachment.name = "Login-Screen-Initial"
attachment.lifetime = .keepAlways
add(attachment)
// Сравнение с эталоном (требует XCTAttachment + golden)
assertScreenshot(
screenshot: screenshot,
goldenName: "login_initial_state"
)
}
}
Xcode Cloud — облачный CI от Apple для сборки и тестирования iOS-приложений. Xcode Cloud поддерживает запуск XCUITest-тестов на симуляторах. Screenshot-тесты можно запускать на нескольких симуляторах параллельно (iPhone 15, iPhone 15 Pro Max, iPad Pro). Результаты: XCResult Bundle с аттачментами. Xcode Cloud не встроен в GitHub/GitLab — используйте Xcode Cloud Webhooks для интеграции. Альтернатива: GitHub Actions с macos-14 и xcodebuild.
Comparison frameworks — iOSSnapshotTestCase (Uber) работает и для screenshot-тестов, если запускать на симуляторе. SwiftSnapshotTesting (pointfree) больше ориентирован на golden-тесты компонентов. Для screenshot-тестов на iOS используйте встроенные средства XCUITest + XCTAttachment + кастомный ImageComparator (Pixelmator или AImage). На CI используйте simulator — на реальных устройствах screenshot-тесты работают только через Device Farm (AWS Device Farm).
Baseline management — эталонные скриншоты хранятся в репозитории (Git LFS) или в S3. Каждый скриншот именуется по шаблону: {testName}_{device}_{orientation}_{locale}.png. Пример: loginScreenPixel7PortraitRu.png. При добавлении нового устройства или локали создаётся новый baseline. При изменении UI старые baseline заменяются новыми после code review. Baseline — это часть кодовой базы, как и исходники тестов.
CI Pipeline — (1) Сборка приложения. (2) Запуск screenshot-тестов на эмуляторах/симуляторах. (3) Сравнение скриншотов с baseline. (4) При несовпадении — генерация diff-изображения. (5) Загрузка diff-артефактов (actual, expected, diff — три файла). (6) Публикация HTML-отчёта с таблицей результатов. (7) Если threshold превышен — тест падает. (8) Reviewer просматривает diff-артефакты и принимает решение: approve (обновить baseline) или reject (фиксить код).
Threshold и tolerance — абсолютное попиксельное сравнение слишком строго. Используйте SSIM (Structural Similarity Index) или MSE (Mean Squared Error). SSIM 0.98 = 98% структурного сходства — хороший порог. Для разных экранов могут потребоваться разные threshold: тёмная тема (больше чёрного — выше точность), градиенты (больше шума — ниже точность). Настраивайте threshold per-test через параметр: @ScreenshotTest(threshold = 0.99).
Device Farm vs Simulator — тесты на реальных устройствах (Firebase Test Lab, AWS Device Farm) дают максимальную реалистичность, но медленные и платные. Тесты на симуляторах/эмуляторах — быстрые и бесплатные, но не показывают real-device особенности (разные GPU, цветопередача дисплея, плотность пикселей). Стратегия: simulator для pre-merge проверки (5 минут), Device Farm для nightly (30 минут, 20 устройств). В IT Sectr используем Firebase Test Lab для ночных прогонов на топ-10 Android-устройств.
Часто задаваемые вопросы
Golden Test — для быстрой проверки отдельных UI-компонентов при каждом коммите (50-200 мс). Screenshot Test — для E2E-проверки целых экранов на реальных устройствах перед релизом (2-30 секунд). Используйте оба: golden для Design System компонентов, screenshot для критических пользовательских путей. Соотношение 80/20 оптимально для большинства проектов.
SSIM 0.98 — хороший стартовый порог для большинства экранов. Для тёмной темы можно 0.99 (выше контраст — точнее сравнение). Для экранов с градиентами и изображениями — 0.95-0.97. Не используйте абсолютное попиксельное сравнение (MSE = 0) — оно даёт 20-30% ложных срабатываний из-за anti-aliasing и разницы GPU. Настраивайте threshold индивидуально под каждый тест.
При каждом intentional изменении UI — изменении цветов, шрифтов, отступов, иконок, добавлении/удалении элементов. Не обновляйте baseline при изменении окружения (версия ОС, шрифты на CI) — это признак flaky test. Baseline обновляется только локально разработчиком после code review: удалил старые baseline, запустил тесты с record=true, проверил новые скриншоты, закоммитил.
Да — через Espresso на Android и XCUITest на iOS. Espresso работает внутри процесса приложения и не требует Accessibility Service (как UI Automator). XCUITest — стандартный фреймворк Apple для UI-тестов. Для screenshot-тестов разница минимальна: XCUITest чуть стабильнее (родной Apple API), UI Automator чуть гибче (межпроцессное взаимодействие).
Если настроены правильно — нет. Pre-merge: запускайте только screenshot-тесты на изменённых экранах (30-60 секунд). Nightly: полный прогон на Device Farm (30 минут, 20 устройств). Время выполнения screenshot-тестов на эмуляторе: 2-10 секунд на экран. 20 экранов = 40-200 секунд. Это меньше, чем время ручного тестирования одного экрана (5-10 минут).
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также