Simple TestFX example fails

时间:2018-10-02 09:08:22

标签: java javafx testfx

Working with TestFX 4.0.14 in Eclipse photon and fx9 or fx11 (doesn't matter), the simple example test from the TestFX wiki fails in should_click_on_button() with

Expected: Labeled has text "clicked!"
         but: was "click me!"

When looking at the screen, the pane and its contained button is shown, but the mouse moves to someplace else: so the button is never clicked and consequently its text never changed.

Any idea what's wrong/how to fix?

The test code (all copied from the wiki for convenience):

import org.junit.Test;
import org.testfx.framework.junit.ApplicationTest;

import static org.testfx.api.FxAssert.*;
import static org.testfx.matcher.control.LabeledMatchers.*;

import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
 * Simple testfx example from testfx wiki:
 * https://github.com/TestFX/TestFX/wiki/Getting-Started
 * 
 */
public class ClickApplicationTest extends ApplicationTest {
    @Override
    public void start(Stage stage) {
        Parent sceneRoot = new ClickApplication.ClickPane();
        Scene scene = new Scene(sceneRoot, 100, 100);
        stage.setScene(scene);
        stage.show();
    }

    @Test
    public void should_contain_button() {
        // expect:
        verifyThat(".button", hasText("click me!"));
    }

    @Test
    public void should_click_on_button() {
        // when:
        clickOn(".button");

        // then:
        verifyThat(".button", hasText("clicked!"));
    }


}

The application code:

import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

/**
 * Simple testfx example from testfx wiki:
 * https://github.com/TestFX/TestFX/wiki/Getting-Started
 * 
 */
public class ClickApplication extends Application {
    // application for acceptance tests.
    @Override public void start(Stage stage) {
        Parent sceneRoot = new ClickPane();
        Scene scene = new Scene(sceneRoot, 100, 100);
        stage.setScene(scene);
        stage.show();
    }

    // scene object for unit tests
    public static class ClickPane extends StackPane {
        public ClickPane() {
            super();
            Button button = new Button("click me!");
            button.setOnAction(actionEvent -> button.setText("clicked!"));
            getChildren().add(button);
        }
    }
}

Update:

Found an open issue in TestFX that might match. It mentions a core fx bug that might be the reason - but doesn't seem to be: it's fixed in fx11 (verified that the code in the core bug report passes), but the testfx issue prevails ..

2 个答案:

答案 0 :(得分:1)

对我有用。

无论如何,您可能会在UI更改发生之前检查它,因为它是在FX Application线程中完成的,而不是在执行测试的线程中完成的。

使用此行

WaitForAsyncUtils.waitForFxEvents()

clickOnverifyThat调用之间。

答案 1 :(得分:1)

事实证明是有问题的原因有几个:

  • 最根本的是core bug-机器人无法在获胜(只有10个?)HiDPI屏幕上正确移动,所以并不是每个人都经历失败
  • 核心错误已在fx11中修复(使用本机win代码),因此现在公开的fx机器人表现良好
  • 最新版本(4.0.14)中与TestFX机器人相关的代码尚未更新为fx11,回购版本为
  • 默认情况下,TestFX使用仍然失败的AWTRobot(至少在TestFX的情况下,核心错误报告中的示例通过了)
  • 要使TestFX测试在Win HiDPI屏幕上可靠运行,我们需要通过将系统属性 testfx.robot 设置为 glass 来强制使用fx机械手
  • 最后一个怪癖:在测试代码中通过System.getProperties().put("testfx.robot", "glass")以编程方式设置属性时,必须在测试类开始之前执行此操作,即在@BeforeClass注释的方法中(不在@Before或testApp.init())!否则,直接或间接涉及mouseMove的第一个测试将失败,随后的测试会很好(使我感到困惑的原因是失败使人感到困惑;)。

示例:

public class ClickTest extends ApplicationTest {

    @Test
    public void testClick() {
        verifyThat(".button", hasText("click me!"));
        clickOn(".button");
        verifyThat(".button", hasText("clicked!"));
    }

    /**
     * Use glass robot.
     * Note: this must happen once before the class is loaded. Otherwise,
     * the very first test run uses the awt robot
     */
    @BeforeClass
    public static void config() throws Exception {
        System.getProperties().put("testfx.robot", "glass");
    }

    @Override
    public void start(Stage stage) {
        Parent sceneRoot = new ClickPane();
        Scene scene = new Scene(sceneRoot, 100, 100);
        stage.setScene(scene);
        stage.show();
    }

    // scene object for unit tests
    public static class ClickPane extends StackPane {
        public ClickPane() {
            super();
            Button button = new Button("click me!");
            button.setOnAction(actionEvent -> button.setText("clicked!"));
            getChildren().add(button);
        }
    }

    @SuppressWarnings("unused")
    private static final Logger LOG = Logger
            .getLogger(ClickTest.class.getName());
}