This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.
Automated UI testing
CrossFly’s testing framework is not JUnit. Each TestCase runs inside the graphics runtime
(paint thread, EventsProcessor, GL pipeline), and the main assertion is the visual comparison of
screenshots against reference images (golden images). Gateway to Chapter 31.
Anatomy of a TestCase
public class LoginTest extends TestCase {
@Override protected void load() throws Exception {
new LoginScreen().show(); // builds the screen under test
}
@Override public void runTests() throws Exception {
waitWindow(LoginScreen.class);
type(0, TextField.class, "[email protected]"); // types into the 1st TextField
type(1, TextField.class, "senha123");
click("Entrar"); // clicks the button with this text
shot(); // captures and compares against the golden
waitWindow(HomeScreen.class);
shot();
}
@Override protected void unload() { /* clears state */ }
}
Interaction: click(...), type(...), enter(), penDown/penUp/penDrag(...), setText(...).
Discovery: find(index, Classe) / find(texto, Classe). Synchronization: waitWindow(...),
waitAnimation(), waitUIidle(...).
Group and run — TestSuite
TestSuite suite = new TestSuite();
suite.startTests(new TestCase[]{ new LoginTest(), new CadastroTest() });
The suite runs each test, compares the shot() captures against the goldens, and reports
(success/fail/log).
⚠️ Determinism is a prerequisite: DeviceConfig.isTesting
Pixel-by-pixel comparison only matches if rendering is deterministic. Turn on
DeviceConfig.isTesting = true — this pins the cursor, removes timestamps, and makes TimePicker/clock
stable. Without it, the golden never matches (blinking cursor, current time, etc. change the image).
Without UI: WindowlessTestCase
For logic that doesn’t need a screen (repository, formatting), extend WindowlessTestCase — it runs on
the runtime, but without building UI.
Generate the doc images
The same test screenshots serve to generate the documentation/store images:
Main.getScreenShot(true).toPng("prefixo_").
Best practices
- Always
DeviceConfig.isTesting = truein the test battery. - Use
waitWindow(...)/waitAnimation()beforeshot()— capture a stable frame. - One golden per relevant visual state; regenerate when you change the UI on purpose.
Common mistakes
- A golden that “passes sometimes, fails others” → missing
isTesting/waitAnimation(unstable frame). shot()before the window is fully visible.