javajunitjavafx-2jemmyjemmyfx

Testing multiple JavaFX components using JemmyFX


I am working on a fairly large project which includes a set of custom JavaFX components. For each custom component which is meant to be reused, I have started to write a set of automated tests using JemmyFX and JUnit. During development, I run these from inside Eclipse Juno.

Running the entire suite of tests at once has proven difficult. The problem seems to stem from the fact since I want to test multiple components, I would ideally run a different application for each (so that tests performed on one component do not affect other tests).

I created a base class which does the following:

@BeforeClass
public static void beforeClass() {

    Thread t = new Thread("JavaFX Init Thread") {

        @Override
        public void run() {
            Application.launch(UITester.class, new String[0]);
        }
    };

    t.setDaemon(true);
    t.start();
}

Using this base class, I created a separate class with @Test tests for each custom control. When I run this test suite, the first test case runs fine, but the rest fail:

Exception in thread "JavaFX Init Thread" java.lang.IllegalStateException: Application launch must not be called more than once

I have tried the following ways to address this problem:

Shut down the application

I added the following to the base class:

@AfterClass
public static void afterClass() {
    Platform.exit();
}

Same problem persists. Perhaps because the VM is not restarted between tests?

Put in a guard against restarting the application

I put in a static variable to check and see if perhaps the application is already running. This makes the problem go away when I run the tests from Eclipse. When I run them from the command line, the problem is still there. Not good for when we try to run these tests on the integration server.

Catch the IllegalStateException

This is an odd one. I can catch the exception, and most of my problems go away, except for the fact that every 4 or 5 runs of the entire test suite Ubuntu crashes to the shell and I have to log back in.

So, how do I best write tests for a large suite of custom controls? Is my approach incorrect?


Solution

  • After looking at the source of MarvinFX I was able to implement our test framework in a fashion that addresses my problems. What appears to have contributed most to fix this problem was rebuilding the stage and scene for every test, as demonstrated in this (pseudo) code:

    @Before
    public void before() {
        Node node = generateComponentToTest();
        Parent parent = StackPaneBuilder.create().children(node).build();
        Scene scene = SceneBuilder.create().root(parent).build();
    
        if (this.currentStage != null) {
            this.currentStage.close();
        }
    
        Stage stage = new Stage();
        stage.setScene(scene);
        stage.centerOnScreen();
        stage.show();
    
        this.currentStage = stage;
    }