7

在 Eclipse photon 和 fx9 或 fx11(没关系)中使用 TestFX 4.0.14,来自 TestFX wiki 的简单示例测试失败should_click_on_button()

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

查看屏幕时,会显示窗格及其包含的按钮,但鼠标会移动到其他位置:因此该按钮永远不会被单击,因此其文本永远不会改变。

知道出了什么问题/如何解决吗?

测试代码(为方便起见,全部从 wiki 复制):

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!"));
    }


}

申请代码:

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);
        }
    }
}

更新:

TestFX中发现了一个可能匹配的未解决问题。它提到了可能是原因的核心 fx 错误- 但似乎不是:它已在 fx11 中修复(已验证核心错误报告中的代码通过),但 testfx 问题占主导地位..

4

2 回答 2

3

这个对我有用。

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

使用这条线

WaitForAsyncUtils.waitForFxEvents()

clickOnverifyThat调用之间。

于 2018-10-02T10:15:12.050 回答
3

原来是一个问题有几个原因:

  • 最根本的是一个核心错误- 机器人在获胜时无法正确移动(仅 10 个?) HiDPI 屏幕,所以不是每个人都经历过失败
  • fx11 中修复了核心错误(在本机 win 代码中),因此现在公开的 fx 机器人表现良好
  • 最新版本(4.0.14)中TestFX机器人相关代码尚未更新到fx11,repo版本为
  • 默认情况下,TestFX 使用仍然失败的 AWTRobot(至少在 TestFX 的上下文中,核心错误报告中的示例通过)
  • 为了使 TestFX 测试在 win HiDPI 屏幕上可靠运行,我们需要强制使用 fx 机器人,通过将系统属性testfx.robot设置为glass
  • 最后一个怪癖:在 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());
}
于 2018-10-05T12:37:21.610 回答