Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting started with TestFx

I'm having some trouble getting TestFx working with Oracle's JavaFx HelloWorld app:

public class HelloWorld extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello World!");
        Button btn = new Button();
        btn.setText("Say 'Hello World'");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                System.out.println("Hello World!");
            }
        });

        StackPane root = new StackPane();
        root.getChildren().add(btn);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }
}

TestFx junit test:

class MyTest extends GuiTest {
  public Parent getRootNode() {
    return nodeUnderTest;
  }

What should nodeUnderTest be for this example?

like image 561
yellavon Avatar asked Dec 09 '14 19:12

yellavon


People also ask

How to use TestFX Java?

To begin using TestFX we need to first make some changes to our test file. Recall that in Main. java, the Main class extends the Application class. Likewise when we want to use TestFX to perform testing of our Main class, we must extend the ApplicationTest class from the org.

What is TestFX?

TestFx is a unit test framework, so it is designed to grab parts of your GUI implementation and test on that.


2 Answers

TestFx is a unit test framework, so it is designed to grab parts of your GUI implementation and test on that. That requires you to make these parts available first and test targets (buttons etc) available by tagging them with ids.

getRootNode() provides the root for the following test procedures of GUI testing. In your example above the StackPane root might be a candidate... but that requires that you make that available for testing to allow:

 class MyTest extends GuiTest {
     public Parent getRootNode() {
         HelloWorld app = new HelloWorld();
         return app.getRoot(); // the root StackPane with button
     }
 }

So the app has to be modified to implement the getRoot(), returning the StackPane with its content for testing, not requiring the start() method.

The you are able to run tests on that...

@Test
public void testButtonClick(){
    final Button button = find("#button"); // requires your button to be tagged with setId("button")
    click(button);
    // verify any state change expected on click.
}
like image 65
Jens-Peter Haack Avatar answered Oct 05 '22 15:10

Jens-Peter Haack


There is also a simple way to test your entire application. To make sure that your app is properly initialised and started, it needs to be started by the JavaFX application launcher. Unfortunately, TestFX doesn't support this out of the box (at least I haven't found any way to do this) but you can easily do this by subclassing GuiTest:

public class HelloWorldGuiTest extends GuiTest {
  private static final SettableFuture<Stage> stageFuture = SettableFuture.create();

  protected static class TestHelloWorld extends HelloWorld {
    public TestHelloWorld() {
      super();
    }

    @Override
    public void start(Stage primaryStage) throws IOException {
      super.start(primaryStage);
      stageFuture.set(primaryStage);
    }
  }

  @Before
  @Override
  public void setupStage() throws Throwable {
    assumeTrue(!UserInputDetector.instance.hasDetectedUserInput());

    FXTestUtils.launchApp(TestHelloWorld.class); // You can add start parameters here
    try {
      stage = targetWindow(stageFuture.get(25, TimeUnit.SECONDS));
      FXTestUtils.bringToFront(stage);
    } catch (Exception e) {
      throw new RuntimeException("Unable to show stage", e);
    }
  }

  @Override
  protected Parent getRootNode() {
    return stage.getScene().getRoot();
  }

  // Add your tests here

}
like image 45
Jan Gassen Avatar answered Oct 05 '22 15:10

Jan Gassen