How to test your JavaFX FXML with TestFX

3 min read
I am writing this tutorial because I really like the simplicity of TestFX and there are just a few TestFX tutorials only. In my opinion there could be more of it. Especially on a beginners level. Therefore this blog post will introduce in testing JavaFX FXML views with JavaFX.

Introduction to TestFX

TestFX offers a fluent and clean API with a flexible setup and cleanup of JavaFX test fixtures. It also offers simple robots to simulate user interactions with a rich collection of matchers to verify expected states and many other cool features. For more informations see: https://github.com/TestFX/TestFX#features

Getting started with maven

Adding TestFX dependency is as simple as adding the JUnit one. You simply have to add the following snippet to your pom.xml. That's all.
<dependency>
<groupId>org.loadui</groupId>
<artifactId>testFx</artifactId>
<version>3.1.2</version>
</dependency>
Note: The upcoming version of TestFX 4.0.x is currently in alpha state. I will update this tutorial once the stable version is released.

Initialize your first empty test class

Each test class has to extend org.loadui.testfx.GuiTest. After extending GuiTest you have to override the getRootNode() method:
public class SampleTest extends GuiTest {

    @Override
    protected Parent getRootNode() {
        Parent parent = null;
        try {
            parent = FXMLLoader.load(getClass().getResource("sample.fxml"));
            return parent;
        } catch (IOException ex) {
            // TODO ...
        }
        return parent;
    }
// ...
}
and you also get additional UI test methods like:find(),click(), scroll(), ... and lots of other methods to simulate user interactions with JUnit tests.

The sample application

The following window simulates a very simple search formular for customers. The windows logic is as simple as the window itself.


The user can search for customers if and only if he enters a first- and also a lastname. In case the user entered firstname or lastname only, the button stays uneditable (grey). The following snippet shows the controller which implements the logic described before.
public class SampleController implements Initializable {
   
    @FXML private TextField firstname;
    @FXML private TextField lastname;
    @FXML private Button search;
   
    @FXML
    private void handleButtonAction(ActionEvent event) {
        // ...
    }
   
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        search.disableProperty().bind(
        firstname.textProperty().isEmpty()
        .or(
        lastname.textProperty().isEmpty()
        ));
    }
}

Writing a test for the sample application

The sample test for this minimalistic application requires all the sections described before. You have to extend GuiTest, override getRootNode() method and use the additional UI methods like find(), verifyThat and so on.
public class SampleTest extends GuiTest {

    @Override
    protected Parent getRootNode() {
        // see snippet before
    }

    @Test
    public void setBothnamesAndCheckEnabledSearchButton() {
        TextField firstname = find("#firstname");
        firstname.setText("bennet");
        verifyThat("#firstname", hasText("bennet"));

        TextField lastname = find("#lastname");
        lastname.setText("schulz");
        verifyThat("#lastname", hasText("schulz"));

        Button search = find("#search");
        assertFalse(search.disableProperty().get());
    }
}
For these two Buttons there are 2^n = 4 different cases you have to test, whereas n=2 is the possible state (enabled or disabled) of each button. The other three cases left are missing to keep the simplicity of this tutorial.
Like you can see, there are lots of similarities with JUnit and every developer experienced with JUnit is able to write tests with TestFX within just a few minutes.

Have fun with TestFX :-)


Be Social, Share!