Alex is a Software Engineer working on Android development tools, especially Android Studio, at Google. His interests include Java, API design, OOP, IDEs and testing. Alex spends some of his spare time working on Open Source, blogging, writing technical articles, and speaking at international conferences. The opinions expressed here represent his own and not those of his employer. Alex is a DZone MVB and is not an employee of DZone and has posted 49 posts at DZone. You can read more from them at their website. View Full User Profile

Making Progress on the JavaFX UI Testing Front

04.29.2010
| 4112 views |
  • submit to reddit

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!

 

From http://alexruiz.developerblogs.com/?p=1163

Published at DZone with permission of Alex Ruiz, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags: