Testes de snapshot para aplicações móveis: como funcionam, ferramentas e exemplos

Autor: IT Sectr Publicado: 2026-04-07 Tempo de leitura: 9 min

O teste de snapshot é um método de verificação automatizada da interface do usuário onde o estado atual da tela é comparado com uma imagem de referência (snapshot) salva durante a execução anterior do teste. Qualquer discrepância visual é registrada como uma alteração que requer confirmação do desenvolvedor. Ao contrário dos testes de UI que verificam a presença de elementos, os testes de snapshot detectam mudanças em nível de pixel — deslocamentos, desvios de cor e problemas de layout. De acordo com Android Developers, 2024, o teste de snapshot detecta até 30% das regressões visuais que passam despercebidas nos testes de UI tradicionais, tornando-o uma ferramenta indispensável para manter uma interface consistente.

Principais pontos

  • Teste de snapshot — um método de comparação da renderização atual da tela com uma imagem de referência para detectar regressões visuais.
  • Paparazzi — uma biblioteca para Android que renderiza componentes Compose e View em ambiente de teste sem iniciar um emulador.
  • Shot — um framework para Android que captura screenshots de telas reais em testes de Instrumentation com suporte a várias resoluções.
  • SnapshotTesting — uma biblioteca da Point-Free para iOS que suporta comparação não apenas de imagens, mas também de texto, JSON e dados do Core Data.
  • Atualização de referências — um comando único após uma alteração intencional na interface, substituindo snapshots antigos por novos.

O que é teste de snapshot?

O teste de snapshot (teste de instantâneo) é uma técnica na qual um teste renderiza um componente de interface, salva a imagem resultante como referência e, em execuções subsequentes, compara a renderização atual com essa referência. Se as imagens coincidirem — o teste passa. Se forem encontradas diferenças — o teste falha, e o desenvolvedor recebe uma imagem diff com os pixels alterados destacados. A técnica foi emprestada do desenvolvimento web (Jest snapshots) e adaptada para plataformas móveis.

O principal valor dos testes de snapshot é a detecção automática de mudanças visuais inesperadas. Um desenvolvedor pode alterar o esquema de cores em um tema global e afetar acidentalmente uma dúzia de telas. Testes de UI que verificam a presença de botões e textos não notarão isso. Um teste de snapshot capturará cada mudança de pixel em cada tela afetada, fornecendo uma imagem completa do impacto da alteração.

De acordo com a pesquisa do Mobile DevOps Summit 2023, equipes que usam testes de snapshot além dos testes de UI clássicos reduzem o número de defeitos visuais em lançamentos em 40%. Essa abordagem é especialmente eficaz em projetos com sistemas de design e arquiteturas baseadas em componentes, onde a alteração de um componente base pode afetar dezenas de telas da aplicação.

Diferenças entre testes de snapshot e testes de UI

A diferença fundamental está no objeto de verificação. Os testes de UI verificam a presença, o estado e o comportamento dos elementos da interface: “o botão está visível”, “o texto contém uma mensagem de erro”, “ao pressionar abre uma nova tela”. Os testes de snapshot verificam a aparência visual completa: posicionamento dos elementos, margens, cores, fontes, sombras e bordas arredondadas. Um teste de snapshot responde à pergunta “a tela parece como esperado?”, enquanto um teste de UI responde “a tela funciona como esperado?”

A velocidade de execução também difere. Os testes de UI são executados em um emulador ou dispositivo real, exigem carregamento completo da aplicação e levam de 10 segundos a um minuto por cenário. Os testes de snapshot com bibliotecas como Paparazzi renderizam componentes em um ambiente virtual sem iniciar um emulador, reduzindo o tempo de teste para 100–500 milissegundos. Um conjunto completo de testes de snapshot (50–100 telas) é executado em 2–5 minutos em vez de 30–60 minutos para um conjunto comparável de testes de UI.

No entanto, os testes de snapshot não substituem os testes de UI. A estratégia ideal é uma combinação: os testes de snapshot cobrem a regressão visual (renderização de cada tela em estados básicos), enquanto os testes de UI cobrem os aspectos comportamentais (cenários de clique, validação de entrada, navegação). Essa combinação proporciona 90% de confiança na correção da interface com tempo mínimo de execução em CI.

Ferramentas para teste de snapshot

No Android, as principais ferramentas são Paparazzi e Shot. O Paparazzi da Cash App renderiza componentes em um ambiente de teste JVM sem emulador, usando o layout de gravidade Layoutlib. O Shot da Karumi realiza screenshots de Instrumentation em um dispositivo real ou emulador e os compara com as referências através da biblioteca AShot, levando em conta diferenças de resolução e densidade de pixels.

Paparazzi para Android

Paparazzi não requer iniciar um emulador — a renderização é feita na JVM através do Layoutlib, proporcionando velocidade comparável a testes unitários. A biblioteca suporta tanto o sistema View quanto o Jetpack Compose. Para Compose, use o modificador paparazzi.snapshot { MyComposable() }. As referências são armazenadas em src/test/snapshots e comparadas automaticamente a cada execução. A porcentagem máxima de diferença é configurável através de maxPercentDifference.

SnapshotTesting para iOS

SnapshotTesting da Point-Free suporta comparação não apenas de UIImage, mas também de strings, JSON, Data e stores inteiras do Core Data. Isso a torna uma ferramenta versátil não apenas para snapshots de UI, mas também para verificar serialização e decodificação de respostas JSON. Para SwiftUI, use a extensão assertSnapshot com o modificador .image(on: .iPhone13). A estratégia record: true cria referências na primeira execução.

Abordagens multiplataforma

Para React Native, a solução popular é react-native-testing-library combinada com jest-image-snapshot. A abordagem web de teste de snapshot é transportada para o ambiente móvel renderizando componentes em um ambiente Node.js, seguido pela comparação de snapshots JSON do DOM virtual. Essa abordagem é mais rápida que a nativa, mas menos precisa — ela não leva em conta as particularidades de renderização de fontes e componentes do sistema específicas da plataforma. Para Flutter, o teste golden é usado através do toolkit goldens.

Exemplos de código para testes de snapshot

Vamos ver testes de snapshot para Android (Paparazzi) e iOS (SnapshotTesting). Ambos os exemplos verificam a aparência de um componente — um cartão de usuário com avatar, nome e status. O teste renderiza o componente com dados de teste e compara o resultado com uma imagem de referência armazenada no repositório.

Android: teste de snapshot com Paparazzi

O Paparazzi usa a anotação @Test e o método snapshot() para capturar a renderização. As referências são salvas na pasta src/test/snapshots e carregadas automaticamente na próxima execução para comparação.

kotlin
class UserCardSnapshotTest {

    @get:Rule
    val paparazzi = Paparazzi(
        theme = "Theme.MyApp",
        maxPercentDifference = 0.1
    )

    @Test
    fun userCard_defaultState() {
        val card = UserCard(
            name = "Alice Johnson",
            status = "Online",
            avatarUrl = "https://example.com/avatar.png"
        )
        paparazzi.snapshot(card)
    }

    @Test
    fun userCard_offlineState() {
        val card = UserCard(
            name = "Bob Smith",
            status = "Offline",
            avatarUrl = null
        )
        paparazzi.snapshot(card, name = "user_card_offline")
    }
}

iOS: teste de snapshot com SnapshotTesting

SnapshotTesting usa o modificador .snapshot() dentro de assertSnapshot. A biblioteca determina automaticamente o formato — UIImage para UIView, String para texto, Data para dados binários.

swift
import SnapshotTesting
import XCTest

class UserCardSnapshotTests: XCTestCase {
    func testUserCardDefaultState() {
        let card = UserCardView(
            name: "Alice Johnson",
            status: "Online",
            avatarURL: URL(string: "https://example.com/avatar.png")
        )
        let controller = UIHostingController(rootView: card)
        assertSnapshot(matching: controller, as: .image(on: .iPhone13))
    }

    func testUserCardOfflineState() {
        let card = UserCardView(
            name: "Bob Smith",
            status: "Offline",
            avatarURL: nil
        )
        assertSnapshot(matching: card, as: .image(on: .iPhone13))
    }
}

Fluxo de trabalho do teste de snapshot

Um fluxo de trabalho típico inclui quatro etapas. Primeira execução (modo record): todos os testes de snapshot são executados em modo de gravação — as imagens de referência são criadas e salvas no repositório. Esta etapa é realizada durante a configuração inicial dos testes ou após uma alteração intencional na interface. Após a gravação, as referências são commitadas junto com o código — elas se tornam parte do projeto.

Nas execuções subsequentes, os testes funcionam em modo de comparação: cada nova renderização é comparada com a referência. Se forem encontradas diferenças, uma imagem diff é gerada: pixels que coincidem com a referência são destacados em verde, os diferentes em vermelho. O desenvolvedor estuda o diff e toma uma decisão: se a mudança for esperada (alteração consciente de design), a referência é atualizada com o comando record; se inesperada — o bug é corrigido. A atualização de referências é feita com um único comando: para Paparazzi é `./gradlew recordPaparazzi`, para SnapshotTesting — `assertSnapshot(record: true)`.

De acordo com o Spotify Engineering Blog (2022), equipes que usam o fluxo de trabalho descrito gastam em média 2 minutos por teste analisando imagens diff. Com um conjunto de 50 testes de snapshot, um ciclo completo de atualização de referências leva de 15 a 20 minutos, significativamente mais rápido do que a verificação manual de mudanças visuais em 50 telas.

Limitações e antipadrões dos testes de snapshot

Os testes de snapshot têm limitações fundamentais. Sensibilidade ao ambiente: um mesmo componente pode renderizar de forma diferente em diferentes versões do SO, densidades de tela e configurações de fonte. Referências criadas em uma máquina podem diferir da renderização em um servidor CI. A solução é usar parâmetros de ambiente fixos: uma versão específica do Layoutlib para Paparazzi ou um modelo exato de dispositivo para SnapshotTesting.

Antipadrão n.º 1: snapshots gigantes — um teste de snapshot que captura a tela inteira falha a cada mudança mínima em qualquer componente. A abordagem correta é testar componentes individuais (botão, cartão, campo de entrada) isoladamente. Cada componente é testado de forma independente, fornecendo identificação precisa da fonte da alteração. Antipadrão n.º 2: ignorar diffs — atualizar automaticamente as referências sem analisar as imagens diff reduz o valor dos testes de snapshot a zero. Cada diff requer uma decisão consciente do desenvolvedor.

De acordo com o Better Engineering Blog (2023), os testes de snapshot trazem maior valor quando cobrem componentes do sistema de design e telas principais em estados básicos — vazio, preenchido, erro e limite. Cobrir animações e estados dinâmicos com testes de snapshot é ineficiente devido à natureza não determinística dos timestamps na renderização — para esses cenários, gravação de vídeo ou verificação manual de QA são mais adequados.

Perguntas frequentes

Os testes de snapshot substituem os testes de UI?

Não, os testes de snapshot verificam a aparência visual, enquanto os testes de UI verificam o comportamento da interface. A estratégia ideal é combinar ambas as abordagens: snapshots para regressão visual, testes de UI para cenários e navegação. Snapshots respondem “parece certo?”, testes de UI respondem “funciona certo?”.

Com que frequência as imagens de referência devem ser atualizadas?

As referências são atualizadas a cada alteração consciente de design: uma nova cor de tema, margens modificadas, adição ou remoção de elementos. A atualização é feita através do modo record, após o qual as imagens diff são revisadas na revisão de código para garantir que as mudanças correspondam às expectativas do designer.

Quais componentes devem ser cobertos com testes de snapshot?

Em primeiro lugar, componentes do sistema de design — botões, cartões, campos de entrada, janelas modais. Em seguida, telas principais em estados básicos. Não teste com snapshots animações, WebView, mapas e telas com conteúdo dinâmico — snapshots produzem falsas falhas devido ao não determinismo.

Como lidar com falsas falhas devido a diferentes versões do SO?

Use o mesmo nível de API para os modos record e test. Para Paparazzi, especifique uma versão específica do Layoutlib na configuração. Para SnapshotTesting, fixe o modelo do dispositivo. Referências criadas no Android 14 podem diferir da renderização no Android 12 devido a mudanças nas fontes do sistema e no tema Material.

Testes de snapshot em CI — como configurar?

Em CI, os testes de snapshot são executados em modo de verificação (verify). Se um teste falhar, o CI mostra a imagem diff nos artefatos de build. O modo record (atualização de referências) é executado localmente pelo desenvolvedor ou em uma tarefa de CI separada com acionamento manual. As imagens de referência devem ser commitadas no repositório.

Resumo

  • O teste de snapshot compara a renderização atual do componente com uma imagem de referência, detectando mudanças de pixel e regressões visuais.
  • Paparazzi — uma ferramenta rápida para Android sem emulador; SnapshotTesting — uma biblioteca versátil para iOS da Point-Free.
  • Os testes de snapshot não substituem os testes de UI — eles os complementam: snapshots para o visual, testes de UI para o comportamento.
  • O modo record cria imagens de referência; o modo verify compara as renderizações atuais com elas e gera diffs em caso de discrepâncias.
  • Componentes do sistema de design são alvo prioritário para testes de snapshot, pois suas alterações afetam múltiplas telas.
  • Cada diff requer uma decisão consciente do desenvolvedor — substituir automaticamente as referências sem análise anula o valor dos testes.
  • As imagens de referência são commitadas no repositório e fazem parte da base de código junto com o código fonte dos testes.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também