Hi,
I am working on a typical client/server application that executes calls to remote web services using JavaFX tasks (javafx.concurrent.Task) running on threads from a thread pool (java.util.concurrent.ThreadPoolExecutor). Using TestFX to test this application works well when both client and server are responsive, but as soon as there is heavy load on the machine running the tests, race conditions occur and tests start failing. There appears to be two main problems:
1) Given a sufficiently high system load the primary Stage is not visible or in focus as soon as the tests start running. This leads to keyboard events synthesized with GuiTest.push(KeyCode ...) being delivered to whatever window had focus when the test started, typically IntelliJ IDEA or Cygwin in my case. I have tried to wait for Stage.isShowing() and Stage.isFocused() before starting the main test logic, but these methods return true long before the window is visible and focused on my screen. This is possibly caused by the Stage being placed on top by the window manager, followed by FxToolkit.showStage() calling stage.toBack() and stage.toFront(), but I haven't investigated this in depth.
2) There is no way to determine that all callbacks submitted as result of a JavaFX event have been run and that the application has settled in an idle state. The event handler may submit a task to the thread pool and this task may submit a Runnable to Platform.runLater() etc. Ideally I would like to synchronize using a method such as WaitForAsyncUtils.waitForFxEvents() that atomically takes into account both Runnables submitted to Platform.runLater() and tasks submitted to my thread pool. I have a semi-working hack for this using PowerMock and Mockito to intercept calls to Platform.runLater() and update a global counter of pending runnables/tasks, but this seems inelegant.
How do you guys deal with issues like these?
Regards,
Oddbjørn Kvalsund