# Testes automatizados de UI

> TestCase/TestSuite rodando no runtime gráfico, com comparação visual de screenshots (golden images).

Source: https://crossfly.dev/pt/docs/best-practices/testes — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Testes automatizados de UI

O framework de testes do CrossFly **não é JUnit**. Cada `TestCase` roda **dentro do runtime gráfico**
(paint thread, `EventsProcessor`, pipeline GL), e a asserção principal é a **comparação visual de
screenshots** contra imagens-referência (*golden images*). Portal para o
Capítulo 31.

## Anatomia de um `TestCase`
```java
public class LoginTest extends TestCase {
   @Override protected void load() throws Exception {
      new LoginScreen().show();        // monta a tela sob teste
   }
   @Override public void runTests() throws Exception {
      waitWindow(LoginScreen.class);
      type(0, TextField.class, "usuario@app.com");   // digita no 1º TextField
      type(1, TextField.class, "senha123");
      click("Entrar");                 // clica no botão com esse texto
      shot();                          // captura e compara com o golden
      waitWindow(HomeScreen.class);
      shot();
   }
   @Override protected void unload() { /* limpa estado */ }
}
```
Interação: `click(...)`, `type(...)`, `enter()`, `penDown/penUp/penDrag(...)`, `setText(...)`.
Descoberta: `find(index, Classe)` / `find(texto, Classe)`. Sincronização: `waitWindow(...)`,
`waitAnimation()`, `waitUIidle(...)`.

## Agrupar e rodar — `TestSuite`
```java
TestSuite suite = new TestSuite();
suite.startTests(new TestCase[]{ new LoginTest(), new CadastroTest() });
```
A suite roda cada teste, compara os `shot()` com os goldens e reporta (`success`/`fail`/`log`).

## ⚠️ Determinismo é pré-requisito: `DeviceConfig.isTesting`
A comparação pixel-a-pixel só casa se a renderização for **determinística**. Ligue
`DeviceConfig.isTesting = true` — isso fixa o cursor, remove timestamps e torna `TimePicker`/relógio
estáveis. **Sem isso, o golden nunca bate** (cursor piscando, hora atual, etc. mudam a imagem).

## Sem UI: `WindowlessTestCase`
Para lógica que não precisa de tela (repository, formatação), estenda `WindowlessTestCase` — roda no
runtime, mas sem montar UI.

## Gerar as imagens da doc
Os mesmos screenshots de teste servem para **gerar as imagens da documentação/loja**:
`Main.getScreenShot(true).toPng("prefixo_")`.

## Boas práticas
- **Sempre** `DeviceConfig.isTesting = true` na bateria de testes.
- Use `waitWindow(...)`/`waitAnimation()` antes de `shot()` — capture um frame **estável**.
- Um golden por estado visual relevante; regenere ao mudar a UI de propósito.

## Erros comuns
- Golden que "some vez sim, vez não" → faltou `isTesting`/`waitAnimation` (frame instável).
- `shot()` antes da janela estar totalmente visível.
