---
title: "Testes de Screenshot no Compose com Kotlin em 2026 | Kotlin Brasil"
url: "https://kotlin.dev.br/blog/testes-screenshot-compose-kotlin-2026/"
markdown_url: "https://kotlin.dev.br/blog/testes-screenshot-compose-kotlin-2026.MD"
description: "Aprenda a usar testes de screenshot no Jetpack Compose com Kotlin para evitar regressões visuais, organizar baselines e integrar validação no CI."
date: "2026-05-24"
author: "Karina Melo"
---

# Testes de Screenshot no Compose com Kotlin em 2026 | Kotlin Brasil

Aprenda a usar testes de screenshot no Jetpack Compose com Kotlin para evitar regressões visuais, organizar baselines e integrar validação no CI.


Testes automatizados costumam entrar em projetos Android pela porta dos repositories, use cases e ViewModels. Isso é ótimo, mas deixa uma pergunta importante sem resposta: quem garante que a interface não quebrou visualmente? Um `Text` truncado, um botão sem contraste, um card desalinhado ou um estado vazio com espaçamento errado podem passar por testes unitários perfeitos. Em apps escritos com **Jetpack Compose e Kotlin**, os testes de screenshot ajudam a fechar essa lacuna.

Screenshot testing não substitui teste unitário, teste de integração nem teste manual exploratório. Ele serve para detectar regressões visuais comparando uma imagem atual da UI com uma imagem de referência aprovada pelo time. Quando o diff aparece, alguém revisa: se a mudança era intencional, o baseline é atualizado; se era acidental, o código volta para o caminho correto.

Esse tipo de validação ficou mais relevante em 2026 porque muitos times já adotaram Compose em produção, modularizaram design systems e passaram a entregar telas em ciclos curtos. Se você já estudou [Jetpack Compose](/guias/guia-jetpack-compose/), [MVVM com Kotlin](/tutoriais/kotlin-mvvm-tutorial/) e [testes com JUnit 5 e MockK](/blog/kotlin-testes-junit5-mockk-guia/), screenshot testing é o próximo passo natural para proteger a camada visual.

## O que um teste de screenshot valida?

Um teste de screenshot captura a renderização de um componente ou tela em um cenário controlado. Depois, compara essa captura com uma imagem salva no repositório ou em um artefato de referência. A validação responde perguntas como:

- o layout continua respeitando o espaçamento esperado;
- o tema claro e o tema escuro ainda renderizam corretamente;
- estados de loading, erro e conteúdo real estão visíveis;
- textos longos não quebram o design;
- mudanças no design system não alteraram telas sem querer.

Isso é especialmente útil em Compose porque componentes pequenos são fáceis de isolar. Você pode testar um `ProdutoCard`, um `EmptyState`, uma barra de filtros ou uma tela inteira com dados fake. Quanto menor o recorte, mais rápido o teste roda e mais fácil fica entender o diff.

## Quando vale a pena usar?

O melhor uso não é fotografar todas as telas do app sem critério. Isso cria baselines demais, aumenta ruído no pull request e transforma cada ajuste de espaçamento em dor operacional. Comece pelos pontos de maior risco:

- componentes reutilizados em muitas telas;
- telas que impactam conversão, onboarding ou pagamento;
- estados vazios, erros e permissões negadas;
- design system compartilhado entre múltiplos módulos;
- telas com muito conteúdo dinâmico ou regras de responsividade.

Um app de delivery, por exemplo, pode começar pelos cards de restaurante, carrinho, resumo do pedido e tela de erro de pagamento. Um app corporativo offline-first pode priorizar listas, estados de sincronização e alertas de conflito. O critério é simples: se uma regressão visual ali geraria bug perceptível para o usuário, vale considerar screenshot test.

## Estrutura recomendada no projeto

Uma organização prática é separar três coisas: previews ou fixtures visuais, testes de screenshot e baselines. Em um módulo Android com Compose, a estrutura pode ficar assim:

```text
app/
  src/
    debug/
      java/br/com/exemplo/ui/preview/
        PedidoFixtures.kt
    screenshotTest/
      java/br/com/exemplo/ui/
        PedidoCardScreenshotTest.kt
      screenshots/
        PedidoCard_light.png
        PedidoCard_dark.png
```

Os detalhes mudam conforme a biblioteca usada, mas a disciplina é a mesma. Os dados usados no teste devem ser determinísticos. Nada de `LocalDateTime.now()` livre, URL remota, fonte baixada em runtime ou texto vindo de API. Quanto mais estável o cenário, menos falsos positivos aparecem.

## Exemplo de componente testável

Imagine um card simples de pedido. Ele recebe dados prontos, não busca nada sozinho e não depende de estado global. Isso torna o componente ideal para screenshot testing.

```kotlin
data class PedidoUi(
    val numero: String,
    val cliente: String,
    val status: String,
    val total: String,
)

@Composable
fun PedidoCard(
    pedido: PedidoUi,
    modifier: Modifier = Modifier,
) {
    Card(modifier = modifier.fillMaxWidth()) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text(
                text = "Pedido #${pedido.numero}",
                style = MaterialTheme.typography.titleMedium,
            )
            Text(text = pedido.cliente)
            Spacer(modifier = Modifier.height(8.dp))
            Text(text = pedido.status)
            Text(
                text = pedido.total,
                style = MaterialTheme.typography.bodyLarge,
                fontWeight = FontWeight.Bold,
            )
        }
    }
}
```

O segredo está em manter o componente previsível. Se ele recebe `PedidoUi`, você consegue montar cenários claros: pedido novo, pedido cancelado, cliente com nome longo, total alto, status em duas linhas. Esses cenários também funcionam bem como `@Preview`, documentação viva para designers e referência para QA.

## Exemplo conceitual de teste

Cada ferramenta tem sua API, mas um teste de screenshot costuma seguir o mesmo fluxo: renderizar Compose, aplicar tema, capturar imagem e comparar com baseline.

```kotlin
class PedidoCardScreenshotTest {
    @get:Rule
    val composeRule = createComposeRule()

    @Test
    fun pedidoCard_estadoPago_temaClaro() {
        composeRule.setContent {
            KotlinBrasilTheme(darkTheme = false) {
                PedidoCard(
                    pedido = PedidoUi(
                        numero = "1042",
                        cliente = "Mariana Oliveira",
                        status = "Pagamento confirmado",
                        total = "R$ 149,90",
                    ),
                )
            }
        }

        composeRule
            .onRoot()
            .captureToImage()
            .assertMatchesBaseline("PedidoCard_estadoPago_temaClaro")
    }
}
```

O método `assertMatchesBaseline` acima é ilustrativo. Na prática, ele pode vir de uma biblioteca específica ou de uma integração interna do time. O importante é que o teste tenha nome descritivo, cenário estável e baseline versionado.

## Como reduzir falsos positivos

Screenshot testing fica ruim quando o ambiente muda demais. Diferenças de fonte, densidade, antialiasing, idioma, timezone e tamanho de tela podem gerar diffs sem mudança real de produto. Para evitar isso:

- fixe dimensões e densidade do dispositivo de teste;
- use dados fake determinísticos;
- evite relógio real, rede real e animações rodando;
- teste tema claro e escuro separadamente;
- padronize fonte e renderização no CI;
- mantenha tolerância visual baixa, mas não ingênua.

Se o teste roda em emulador, o ambiente do CI precisa ser previsível. Se roda em renderização local no JVM, confira as limitações da ferramenta para componentes que dependem de APIs Android específicas. Em ambos os casos, documente como atualizar baselines. Nada pior do que um teste que falha corretamente, mas ninguém sabe revisar.

## Integração com CI/CD

O fluxo ideal em pull requests é simples: testes unitários continuam rodando primeiro; testes de screenshot entram depois, talvez apenas nos módulos de UI alterados; quando há diff, o CI publica os artefatos para revisão. O time então decide se a alteração visual é desejada.

Um pipeline conceitual pode ter etapas assim:

```yaml
steps:
  - name: Run unit tests
    run: ./gradlew testDebugUnitTest

  - name: Run screenshot tests
    run: ./gradlew validateDebugScreenshotTest

  - name: Upload screenshot diffs
    if: failure()
    uses: actions/upload-artifact@v4
    with:
      name: screenshot-diffs
      path: app/build/reports/screenshot
```

Se você já tem um pipeline parecido com o do nosso guia de [CI/CD para Kotlin](/guias/guia-kotlin-ci-cd/) ou com [GitHub Actions em projetos Kotlin](/blog/kotlin-github-actions/), a lógica encaixa bem. A diferença é cultural: o reviewer precisa olhar o diff visual com a mesma seriedade que olha uma mudança de código.

## Como lidar com baselines no repositório

Versionar baselines no Git costuma ser a escolha mais simples para times pequenos e médios. As imagens ficam próximas dos testes, cada alteração aparece no pull request e o histórico mostra quando a UI mudou. Para times maiores, pode fazer sentido armazenar baselines em um serviço dedicado, mas isso aumenta complexidade.

Algumas regras ajudam bastante:

- não atualize baseline junto com mudança não relacionada;
- escreva no commit por que a UI mudou;
- revise diffs em tema claro, escuro e tamanhos relevantes;
- remova baselines de componentes deletados;
- evite snapshots gigantes de fluxos completos quando um componente pequeno resolve.

Pense no baseline como contrato visual. Ele não é “arquivo gerado qualquer”. É uma decisão de produto capturada em imagem.

## Relação com previews e testes manuais

Compose Preview continua útil para desenvolvimento rápido, documentação de estados e conversa com design. Screenshot testing adiciona automação e histórico. Teste manual continua necessário para gestos, acessibilidade real, navegação, performance e sensação de uso.

Um bom fluxo usa os três. O desenvolvedor cria previews para os principais estados, promove os estados críticos para screenshot tests e ainda valida manualmente a experiência em dispositivo real antes de mudanças importantes. Para interfaces complexas, isso reduz retrabalho porque bugs visuais aparecem cedo, não depois do QA ou da publicação na Play Store.

## Cuidados com acessibilidade

Screenshot testing mostra pixels, mas não entende tudo sobre acessibilidade. Um texto pode parecer correto e ainda ter descrição ruim para leitor de tela. Um botão pode estar visível e não ter área de toque suficiente. Por isso, combine screenshots com validações semânticas do Compose UI Test quando possível.

```kotlin
composeRule
    .onNodeWithContentDescription("Confirmar pedido")
    .assertIsDisplayed()
    .assertHasClickAction()
```

Essa combinação protege tanto a aparência quanto a intenção da interface. Para times Android profissionais, esse é o ponto de maturidade: testar comportamento, estado, acessibilidade e regressão visual sem transformar o pipeline em uma parede lenta e frágil.

## Próximos passos

Comece pequeno. Escolha um componente de alto reuso, crie dois ou três cenários, rode localmente, integre ao CI e observe o volume de ruído. Se a experiência for boa, expanda para telas críticas. Se os testes falharem por ambiente, estabilize o ambiente antes de aumentar cobertura.

Também vale comparar essa prática com outros ecossistemas. No frontend web, screenshot testing e visual regression já são comuns há anos; em times que usam <a href="https://python.dev.br/" target="_blank" rel="noopener noreferrer" onclick="umami.track('portfolio-site-click', { destination: 'python.dev.br' })">Python para automação e QA</a>, ferramentas visuais costumam aparecer junto de Playwright, Selenium ou pipelines de validação de interface. No Android com Kotlin, a vantagem é trazer a mesma disciplina para componentes Compose versionados, tipados e próximos do design system.

Testes de screenshot não são uma bala de prata, mas resolvem uma categoria real de problema: regressões visuais pequenas que passam despercebidas até incomodarem usuários. Em projetos Kotlin modernos, especialmente com Jetpack Compose, eles funcionam melhor quando protegem componentes críticos, rodam em ambiente previsível e fazem parte de uma estratégia maior de qualidade junto com testes unitários, testes de UI, análise estática e revisão humana.
