Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

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 = true in the test battery.
  • Use waitWindow(...)/waitAnimation() before shot() — 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.
Was this page helpful?