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.

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 the MainWindow skeleton 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

Was this page helpful?