Making progress on the JavaFX UI testing front

by Алекс Руис on April 28, 2010


I finally made some progress on FEST-JavaFX! :)

The main obstacle was to find a way to look up UI controls on any JavaFX UI. The problem was that all this time I’ve been working with the wrong node hierarchy, Scenario, instead of the JavaFX one! It was impossible to figure out which node corresponds to a control. JavaFX nodes get compiled into Scenegraph nodes, but those compiled nodes do not have any information about the original JavaFX nodes. In addition, Scenario is a implementation detail that can change at any time.

The solution was under my nose all this time, and I’ve found a couple of hacks that can make testing JavaFX UIs possible.

Note: these hacks work with JavaFX 1.3, but may not work with future releases.

How to start a JavaFX UI from Java

This is the first step for testing any JavaFX UI. Ideally, we’d like to write our UI test in JavaFX script, using the really cool JFXtras‘ test support (soon to be merged to FEST.) IMHO, it is also useful to be able to write UI tests in Java (e.g. to have a choice between JUnit and TestNG.) The following code listing shows how to launch a JavaFX UI, using some reflection magic:

staticMethod("javafx$run$").withReturnType(Object.class)
                           .withParameterTypes(Sequence.class)
                           .in(javaFxClass)
                           .invoke(TypeInfo.String.emptySequence);

where javaFxClass is the class of the JavaFX UI to start.

This method returns a JavaFX Stage. Once we have a Stage we have access to the UI’s Scene, which contains all the JavaFX (not Scenario) nodes and controls in the UI.

Finding a node’s location on the screen: 1st. attempt

Once a JavaFX is launched and we have access to all JavaFX nodes (via the UI’s Stage,) we can simulate user input on any node or control. The problem now is that a JavaFX node does not have a way to return its location on the screen (a method like Swing’s getLocationOnScreen can be handy here.)

The following is my first attempt. It works, but it’s horrible in the sense that it depends on too many internals, and I’m pretty sure it won’t work in the future.

This code listing calculates the center of a control, relative to the screen:

public static Point centerOf(Control control) {
  Point2D center = control.localToScene(control.get$width() / 2, control.get$height() / 2);
  Point where = new Point((int)p.$x, (int)p.$y);
  Stage stage = stageOf(control);
  Point locationOnScreen = locationOnScreenOf(stage);
  where.translate(locationOnScreen.x, locationOnScreen.y);
  return where;
}
 
private static Stage stageOf(Control control) {
  return control.get$scene().get$stage();
}
 
private static Point locationOnScreenOf(Stage stage) {
  Window window = windowFrom(stage);
  return window.getContentPane().getLocationOnScreen();
}
 
private static Window windowFrom(Stage stage) {
  TKStage peer = stage.get$Stage$impl_peer();
  FrameStage frameStage = (FrameStage)peer;
  return frameStage.window;
}

Once we have the screen coordinates of a control, it is easy to simulate user input on it. For example, to simulate a user clicking a button, we can just tell FEST’s Robot where to click.

Conclusion

Now that is possible to look up any node and find its position on the screen, we can apply all the lessons learned while working on FEST-Swing and build a testing tool for JavaFX UIs!

Feedback is always appreciated :)

{ 2 comments… read them below or add one }

Steve Sobczak May 3, 2010 at 7:00 am

This and the FEST JavaFX Maven Plugin are the most exciting activities I’m monitoring. I’ve managed to avoid Maven for the longest time, but FEST for JavaFX has me regretting that decision because I’d really like to become a contributor sooner rather than later. I’m also using OpenEJB with my primary JavaFX app, so building EJBs for it has gotten me warmed up to Maven, but it’d be great to merge the two builds and their tests. I’m really looking forward to more of your updates!

Reply

Alex Ruiz May 3, 2010 at 8:35 am

Thanks Steve!

I’m currently focused on FEST-JavaFX and the Maven plug-in. There is a lot of infrastructure code to build first. I’ll keep you updated with our progress :)

Cheers!

Reply

Leave a Comment

{ 1 trackback }

Previous post:

Next post: