Screenshot Test — zautomatyzowane sprawdzanie interfejsu użytkownika poprzez przechwytywanie i porównywanie zrzutów ekranów aplikacji z obrazami referencyjnymi. W przeciwieństwie do testów golden, testy są wykonywane na rzeczywistych urządzeniach lub emulatorach, przechwytują pełne ekrany z nawigacją, elementami systemowymi i animacjami oraz wykorzystują UI Automator (Android) lub XCUITest (iOS) do interakcji z aplikacją. Więcej — w dokumentacji Android UI Automator.
Najważniejsze
Screenshot Test — to end-to-end testowanie interfejsu użytkownika, podczas którego test otwiera ekran aplikacji, wykonuje akcje (tapnięcia, wprowadzanie tekstu, przewijanie) i robi zrzut ekranu uzyskanego stanu. Zrzut ekranu jest porównywany z wzorcem (baseline) przechowywanym w repozytorium. Jeśli zrzuty ekranu się różnią — test nie przechodzi. Testy screenshot wykrywają regresje wizualne, które nie są widoczne w testach jednostkowych: nieprawidłowe marginesy, nakładanie się elementów, nieprawidłowe kolory.
Po co testy screenshot, skoro są testy golden — testy golden sprawdzają komponenty w izolacji: jeden przycisk, jedna karta, jeden tekst. Testy screenshot sprawdzają cały ekran w środowiku maksymalnie zbliżonym do produkcyjnego: rzeczywista nawigacja, rzeczywiste dane (lub maksymalnie realistyczne mocki), rzeczywiste czcionki systemowe, rzeczywisty pasek statusu. Tylko test screenshot pokaże, że przycisk nakłada się na inny element na rzeczywistym urządzeniu.
Wartość biznesowa — według danych Google (2023), błędy wizualne stanowią 15-25% wszystkich błędów aplikacji mobilnych. Testy screenshot automatyzują sprawdzanie jakości wizualnej, która wcześniej była wykonywana ręcznie przez inżynierów QA. Jeden test screenshot zastępuje 5-10 minut ręcznego testowania jednego ekranu. Dla aplikacji z 50 ekranami oszczędność: 4-8 roboczogodzin na jeden przebieg regresyjny. Testy screenshot zwracają się w ciągu 2-3 cykli wydawniczych.
Testy golden są szybsze i prostsze: renderowanie komponentu w buforze off-screen trwa milisekundy, nie wymaga urządzenia, są stabilne w CI. Testy screenshot są bardziej realistyczne: przechwytują rzeczywisty ekran z elementami systemowymi, obsługują animacje i nawigację, działają na rzeczywistych urządzeniach. Wybór zależy od celu: szybka informacja zwrotna dla programisty (golden) lub maksymalny realizm przed wydaniem (screenshot).
| Cecha | Screenshot Test | Golden Test |
|---|---|---|
| Szybkość | 2-30 sekund | 50-200 ms |
| Realizm | Maksymalny (rzeczywiste urządzenie) | Ograniczony (off-screen) |
| Wymaga urządzenia | Tak (emulator/fizyczne) | Nie (JVM, XCTest) |
| Animacje | Obsługuje | Nie obsługuje |
| Nawigacja | Scenariusze wieloetapowe | Jeden komponent |
| Flakiness | Wysoka (sieć, timing) | Średnia (GPU, czcionki) |
| Równoległość | Device Farm (Firebase, AWS) | Wielowątkowy JVM/XCTest |
Golden + Screenshot — używaj testów golden dla każdego komponentu UI w bibliotece komponentów (Design System). 80% regresji wizualnych jest wychwytywanych na poziomie komponentów. Testy screenshot — dla krytycznych ścieżek użytkownika: onboarding, logowanie, proces płatności, koszyk. 20% regresji związanych z integracją komponentów na rzeczywistym ekranie jest wychwytywanych tylko przez testy screenshot. W IT Sectr używamy proporcji 80/20: 400 golden + 100 screenshot.
Kiedy test screenshot nie jest potrzebny — jeśli ekran składa się ze statycznej treści bez interaktywności, test golden komponentu daje ten sam poziom weryfikacji za niższą cenę. Jeśli ekran zmienia się dynamicznie (kanał, czat), test screenshot wymaga złożonej konfiguracji danych i czasu oczekiwania. W takich przypadkach używaj testu screenshot dla stanu podstawowego (pusta lista, ładowanie) i golden dla poszczególnych kart na liście.
UI Automator — framework Android do międzyaplikacyjnego testowania UI. Pozwala robić zrzuty ekranu przez UiDevice.takeScreenshot(). W przeciwieństwie do Espresso (działa wewnątrz jednej aplikacji), UI Automator może wchodzić w interakcje z oknami systemowymi (uprawnienia, powiadomienia) i innymi aplikacjami. Test screenshot na UI Automator: otworzyć aplikację, poczekać na załadowanie, zrobić zrzut ekranu, porównać z wzorcem.
class LoginScreenScreenshotTest {
@get:Rule
val rule = ComposeTestRule.createAndroidComposeRule<MainActivity>()
@Test
fun login_screen_default() {
val device = UiDevice.getInstance(
InstrumentationRegistry.getInstrumentation()
)
// Czekamy na załadowanie ekranu
IdlingRegistry.getInstance().waitForIdle()
// Robimy zrzut ekranu
val screenshot = device.takeScreenshot()
val golden = loadGolden("login_default.png")
// Porównujemy z wzorcem
val diff = ImageComparator.compare(screenshot, golden)
assertTrue(diff.similarity > 0.98)
}
}
Firebase Test Lab — usługa Google Cloud do uruchamiania testów instrumentalnych na setkach rzeczywistych urządzeń równolegle. Testy screenshot na Firebase Test Lab przechwytują zrzuty ekranu na różnych urządzeniach (Pixel 7, Galaxy S24, Xiaomi 14) i porównują z wzorcami. Zaleta: jeden test sprawdza UI na 20 urządzeniach w 10-15 minut. Wada: koszt ($1-5 za test na 20 urządzeń). Firebase Test Lab integruje się z CI przez gcloud CLI lub wtyczkę Gradle.
Shot — biblioteka do testów screenshot na Androidzie, ułatwiająca tworzenie i porównywanie zrzutów ekranu. Shot działa na bazie Espresso i UI Automator, dodając zarządzanie golden (tworzenie, aktualizacja, usuwanie), porównanie z threshold (piksele lub procenty) i generowanie raportu HTML. Shot jest odpowiedni dla projektów, które chcą szybko wdrożyć testowanie screenshot bez budowania własnej infrastruktury porównywania obrazów.
XCUITest — framework Apple do testowania UI aplikacji iOS, iPadOS i tvOS. Testy screenshot na XCUITest używają XCUIScreen.main.screenshot() do przechwytywania ekranu i XCAttachment do zapisywania zrzutu ekranu. XCUITest symuluje działania użytkownika: tap, swipe, typeText, i robi zrzuty ekranu po każdym kroku. W Xcode 16+ dodano wbudowaną obsługę porównywania zrzutów ekranu z wzorcami przez 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)
// Robimy zrzut ekranu
let screenshot = app.screenshot()
let attachment = XCTAttachment(screenshot: screenshot)
attachment.name = "Login-Screen-Initial"
attachment.lifetime = .keepAlways
add(attachment)
// Porównanie z wzorcem (wymaga XCTAttachment + golden)
assertScreenshot(
screenshot: screenshot,
goldenName: "login_initial_state"
)
}
}
Xcode Cloud — chmurowy CI od Apple do budowania i testowania aplikacji iOS. Xcode Cloud obsługuje uruchamianie testów XCUITest na symulatorach. Testy screenshot można uruchamiać na kilku symulatorach równolegle (iPhone 15, iPhone 15 Pro Max, iPad Pro). Wyniki: XCResult Bundle z załącznikami. Xcode Cloud nie jest wbudowany w GitHub/GitLab — używaj Xcode Cloud Webhooks do integracji. Alternatywa: GitHub Actions z macos-14 i xcodebuild.
Frameworki do porównywania — iOSSnapshotTestCase (Uber) działa również dla testów screenshot, jeśli uruchomić na symulatorze. SwiftSnapshotTesting (pointfree) jest bardziej ukierunkowany na testy golden komponentów. Do testów screenshot na iOS używaj wbudowanych narzędzi XCUITest + XCTAttachment + niestandardowego ImageComparator (Pixelmator lub AImage). W CI używaj symulatora — na rzeczywistych urządzeniach testy screenshot działają tylko przez Device Farm (AWS Device Farm).
Zrządzanie baseline — wzorcowe zrzuty ekranu są przechowywane w repozytorium (Git LFS) lub w S3. Każdy zrzut ekranu jest nazywany według wzorca: {testName}_{device}_{orientation}_{locale}.png. Przykład: loginScreenPixel7PortraitRu.png. Po dodaniu nowego urządzenia lub locale tworzony jest nowy baseline. Po zmianie UI stare baseline są zastępowane nowymi po code review. Baseline jest częścią bazy kodu, tak jak źródła testów.
CI Pipeline — (1) Budowa aplikacji. (2) Uruchomienie testów screenshot na emulatorach/symulatorach. (3) Porównanie zrzutów ekranu z baseline. (4) W przypadku niezgodności — generowanie obrazu diff. (5) Przesłanie artefaktów diff (actual, expected, diff — trzy pliki). (6) Publikacja raportu HTML z tabelą wyników. (7) Jeśli threshold przekroczony — test nie przechodzi. (8) Reviewer przegląda artefakty diff i podejmuje decyzję: approve (aktualizacja baseline) lub reject (poprawa kodu).
Threshold i tolerancja — absolutne porównanie piksel po pikselu jest zbyt rygorystyczne. Używaj SSIM (Structural Similarity Index) lub MSE (Mean Squared Error). SSIM 0.98 = 98% podobieństwa strukturalnego — dobry próg. Dla różnych ekranów mogą być potrzebne różne threshold: tryb ciemny (więcej czarnego — wyższa dokładność), gradienty (więcej szumu — niższa dokładność). Konfiguruj threshold per-test przez parametr: @ScreenshotTest(threshold = 0.99).
Device Farm vs Symulator — testy na rzeczywistych urządzeniach (Firebase Test Lab, AWS Device Farm) dają maksymalny realizm, ale są wolne i płatne. Testy na symulatorach/emulatorach — szybkie i darmowe, ale nie pokazują cech rzeczywistych urządzeń (różne GPU, odwzorowanie kolorów ekranu, gęstość pikseli). Strategia: symulator do weryfikacji pre-merge (5 minut), Device Farm do nightly (30 minut, 20 urządzeń). W IT Sectr używamy Firebase Test Lab do nocnych przebiegów na top-10 urządzeniach Android.
Często zadawane pytania
Golden Test — do szybkiego sprawdzania poszczególnych komponentów UI przy każdym commicie (50-200 ms). Screenshot Test — do E2E sprawdzania całych ekranów na rzeczywistych urządzeniach przed wydaniem (2-30 sekund). Używaj obu: golden dla komponentów Design System, screenshot dla krytycznych ścieżek użytkownika. Proporcja 80/20 jest optymalna dla większości projektów.
SSIM 0.98 — dobry próg początkowy dla większości ekranów. Dla trybu ciemnego można 0.99 (wyższy kontrast — dokładniejsze porównanie). Dla ekranów z gradientami i obrazami — 0.95-0.97. Nie używaj absolutnego porównania piksel po pikselu (MSE = 0) — daje 20-30% fałszywych alarmów z powodu anti-aliasingu i różnic GPU. Konfiguruj threshold indywidualnie dla każdego testu.
Przy każdej celowej zmianie UI — zmianie kolorów, czcionek, marginesów, ikon, dodaniu/usunięciu elementów. Nie aktualizuj baseline przy zmianie środowiska (wersja systemu, czcionki w CI) — to oznaka flaky test. Baseline jest aktualizowany tylko lokalnie przez programistę po code review: usunął stare baseline, uruchomił testy z record=true, sprawdził nowe zrzuty ekranu, zatwierdził.
Tak — przez Espresso na Androidzie i XCUITest na iOS. Espresso działa wewnątrz procesu aplikacji i nie wymaga Accessibility Service (jak UI Automator). XCUITest — standardowy framework Apple do testów UI. Dla testów screenshot różnica jest minimalna: XCUITest jest nieco stabilniejszy (natywny Apple API), UI Automator nieco bardziej elastyczny (komunikacja międzyprocesowa).
Jeśli są poprawnie skonfigurowane — nie. Pre-merge: uruchamiaj tylko testy screenshot na zmienionych ekranach (30-60 sekund). Nightly: pełny przebieg na Device Farm (30 minut, 20 urządzeń). Czas wykonania testów screenshot na emulatorze: 2-10 sekund na ekran. 20 ekranów = 40-200 sekund. To mniej niż czas ręcznego testowania jednego ekranu (5-10 minut).
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również