This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.
11. Testing your app
What you will learn: create a safety net with tests that run in the graphics runtime. Prerequisites: Making it responsive.
Complete example (copy, paste and run)
Unlike the other chapters, here the self-contained example is a complete TestCase (not a
MainWindow): it opens the screen in load(), simulates taps in runTests() and compares the screenshot with the
golden. DeviceConfig.isTesting = true makes rendering deterministic. Compiles as is.
package com.exemplo;
import dev.crossfly.test.*;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
public class AdicionarTarefaTest extends TestCase
{
@Override
protected void load() throws Exception
{
DeviceConfig.isTesting = true; // golden prerequisite (determinism)
new TarefasScreen().show();
}
@Override
public void runTests() throws Exception
{
waitWindow(TarefasScreen.class); // waits for a stable frame
type(0, TextField.class, "Comprar pão"); // types into the 1st TextField
click("Adicionar"); // clicks the button by its text
shot(); // captures and compares against the golden
}
@Override
protected void unload() { }
}
class TarefasScreen extends Window // the screen under test
{
private final TextField campo = new TextField().caption("Nova tarefa");
private final Component listaBox = new Component();
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
add(LAY_AUTO, campo);
Button add = new Button("Adicionar");
add.onAction(c -> {
String t = campo.getText().trim();
if (!t.isEmpty()) { listaBox.add(LAY_AUTO, new Label(t)); campo.clearText(); listaBox.setValidLayout(false); repaint(); }
});
add(LAY_AUTO, add);
listaBox.setLayout(new VerticalLayout());
add(LAY_FILL, listaBox);
}
}
To run the suite:
new TestSuite().startTests(new TestCase[]{ new AdicionarTarefaTest() });
The snippets below show only the core (what goes inside
onShow()). To run them, place them in theMainWindowskeleton above.
Tests run in the graphics runtime (it’s not JUnit)
Each TestCase runs inside the paint thread/GL pipeline; the main assertion is the visual
comparison of screenshots (golden images).
public class AdicionarTarefaTest extends TestCase {
@Override protected void load() throws Exception { new TarefasScreen().show(); }
@Override public void runTests() throws Exception {
waitWindow(TarefasScreen.class);
type(0, TextField.class, "Comprar pão"); // types in the field
click("Adicionar"); // clicks the button
shot(); // captures and compares against the golden
}
@Override protected void unload() { }
}
Run with a TestSuite:
new TestSuite().startTests(new TestCase[]{ new AdicionarTarefaTest() });
⚠️ Determinism: DeviceConfig.isTesting
The pixel-by-pixel comparison only matches if rendering is deterministic. Turn on
DeviceConfig.isTesting = true (fixes the cursor, removes timestamps) — without it, the golden never matches.
Use waitWindow(...)/waitAnimation() before shot() to capture a stable frame.
Direct screenshot
Image atual = Main.getScreenShot(true); // captures the frame (opaque) to compare against the baseline
What you build in this step
Tests to add/persist a task and a visual test of a screen.
Recap
TestCase (load/runTests/unload) + click/type/shot; DeviceConfig.isTesting is
a prerequisite for the golden; capture stable frames.
Next steps
→ Shipping
See also
- Tests (best-practices) · Canonical source: Chapter 31 — Tests