0

Specifically the WriteRobot / WriteRobotImpl. It seems to write things rather slowly and I'd like to make it write faster.

Edit
In response to M.S.'s comment I tried this (NB at this point I hadn't worked out that WriteRobot was involved, not TypeRobot):

setup(){
...
    setFinalStatic( org.testfx.robot.impl.TypeRobotImpl.class.getDeclaredField("SLEEP_AFTER_KEY_CODE_IN_MILLIS"), 5 );
}
...
static void setFinalStatic(Field field, Object newValue) throws Exception {
    field.setAccessible(true);
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, newValue);
}

Unfortunately it appears to make no difference to the typing speed, even when set to 1 ms.

Edit
I note the comment by Slaw.

I set the System property testfx.robot.write_sleep before running the test: this had no effect, despite one being able to see that it might have, from the source code at the top of WriteRobotImpl.java (see below). When I set this to 500 ms it also had no effect, making me conclude that the property was not being seen by the code there for some reason, so the default 25 ms was being set.

NB possible other causes: following the code there, it appears that WriteRobot.write always results in a call to WriteRobot.typeCharacterInScene, which in turn calls BaseRobot.typeKeyboard and WaitForAsyncUtils.waitForFxEvents. The latter might be a "difficult customer": if each pressed key then has to "wait for events" to bubble up, there may well be nothing to be done about things.

Still trying to work out why the following lines at the top of org.testfx.robot.impl.WriteRobotImpl.java would fail to see the System property:

private static final int SLEEP_AFTER_CHARACTER_IN_MILLIS;

static {
    int writeSleep;
    try {
        writeSleep = Integer.getInteger("testfx.robot.write_sleep", 25);
    }
    catch (NumberFormatException e) {
        System.err.println("\"testfx.robot.write_sleep\" property must be a number but was: \"" +
                System.getProperty("testfx.robot.write_sleep") + "\".\nUsing default of \"25\" milliseconds.");
        e.printStackTrace();
        writeSleep = 25;
    }
    SLEEP_AFTER_CHARACTER_IN_MILLIS = writeSleep;
}

I also wondered whether maybe that static{...} code block happens so early than you need to set the System property before the tests are run. I tried setting this property in gradle.build. Still no success.

mike rodent
  • 14,126
  • 11
  • 103
  • 157
  • `SLEEP_AFTER_KEY_CODE_IN_MILLIS = 25` is a private static final field in [`TypeRobotImpl`](https://github.com/TestFX/TestFX/blob/master/subprojects/testfx-core/src/main/java/org/testfx/robot/impl/TypeRobotImpl.java). They also do not allow using a different implementation, so extending the context doesn't solve the problem. I think they should make this field changeable by setting a system property. Anyway, I think reflection is your only way. – Miss Chanandler Bong Apr 06 '20 at 10:41
  • Thanks... Having a bit of trouble: see update. – mike rodent Apr 06 '20 at 12:56
  • You should use `getDeclaredField("SLEEP_AFTER_KEY_CODE_IN_MILLIS")` not `getField("SLEEP_AFTER_KEY_CODE_IN_MILLIS")` – Miss Chanandler Bong Apr 06 '20 at 13:06
  • Thanks. Well I got it working... but it seems (even when set to 1 ms) to make no difference to the typing speed! NB I also checked after setting the field by obtaining it and logging it, just to make sure it had indeed been set. Some other mechanism appears to be involved. – mike rodent Apr 06 '20 at 13:31
  • I read the source code trying to find another reason for the slowness but no luck. – Miss Chanandler Bong Apr 06 '20 at 13:37
  • In fact robot `write` (which writes out an entire `String`) is not handled by `TypeRobotImpl`, but by `org.testfx.api.FxRobot`, or maybe one of its subclasses... investigating source code... (ah, you too? :-) ) – mike rodent Apr 06 '20 at 13:38
  • [WriteRobotImpl](https://github.com/TestFX/TestFX/blob/ca90e066d9339282973e3872212d608402a8d9d6/subprojects/testfx-core/src/main/java/org/testfx/robot/impl/WriteRobotImpl.java)? – Miss Chanandler Bong Apr 06 '20 at 13:41
  • `WriteRobot.write(java.lang.String text, int sleepMillis)` looks promising... – mike rodent Apr 06 '20 at 13:41
  • Use this property: `testfx.robot.write_sleep`, to set a default – Miss Chanandler Bong Apr 06 '20 at 13:41
  • Just a note: You cannot change `private static final long SLEEP_AFTER_KEY_CODE_IN_MILLIS = 25;` via reflection and expect it to have any effect. That is a compile-time constant and as such is inlined everywhere it's used. This behavior is one of the very few optimizations done by the Java compiler (majority of optimizations are done by the JIT at runtime). – Slaw Apr 06 '20 at 13:58

0 Answers0