Java 开始使用TestFx
我在让TestFx与Oracle的JavaFx HelloWorld应用程序配合使用时遇到一些问题:Java 开始使用TestFx,java,unit-testing,testing,javafx,testfx,Java,Unit Testing,Testing,Javafx,Testfx,我在让TestFx与Oracle的JavaFx HelloWorld应用程序配合使用时遇到一些问题: public class HelloWorld extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { primaryStage.
public class HelloWorld extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
对于这个例子,
nodeUnderTest
应该是什么?TestFx是一个单元测试框架,所以它被设计来获取GUI实现的一部分并在此基础上进行测试。这要求您首先使这些部件可用,并使用ID标记测试目标(按钮等)
getRootNode()为以下GUI测试过程提供根目录。在上面的示例中,StackPane根可能是一个候选项。。。但这要求您将其用于测试,以允许:
class MyTest extends GuiTest {
public Parent getRootNode() {
HelloWorld app = new HelloWorld();
return app.getRoot(); // the root StackPane with button
}
}
因此,必须修改应用程序以实现getRoot(),返回StackPane及其内容进行测试,而不需要start()方法
您可以对其运行测试
@Test
public void testButtonClick(){
final Button button = find("#button"); // requires your button to be tagged with setId("button")
click(button);
// verify any state change expected on click.
}
还有一种简单的方法可以测试整个应用程序。要确保应用程序已正确初始化和启动,需要由JavaFX应用程序启动器启动。不幸的是,TestFX不支持这种开箱即用的方式(至少我还没有找到任何方法),但您可以通过子类化GuitTest轻松做到这一点:
public class HelloWorldGuiTest extends GuiTest {
private static final SettableFuture<Stage> stageFuture = SettableFuture.create();
protected static class TestHelloWorld extends HelloWorld {
public TestHelloWorld() {
super();
}
@Override
public void start(Stage primaryStage) throws IOException {
super.start(primaryStage);
stageFuture.set(primaryStage);
}
}
@Before
@Override
public void setupStage() throws Throwable {
assumeTrue(!UserInputDetector.instance.hasDetectedUserInput());
FXTestUtils.launchApp(TestHelloWorld.class); // You can add start parameters here
try {
stage = targetWindow(stageFuture.get(25, TimeUnit.SECONDS));
FXTestUtils.bringToFront(stage);
} catch (Exception e) {
throw new RuntimeException("Unable to show stage", e);
}
}
@Override
protected Parent getRootNode() {
return stage.getScene().getRoot();
}
// Add your tests here
}
公共类HelloWorldGuiTest扩展了GuiTest{
私有静态final SettableFuture stageFuture=SettableFuture.create();
受保护的静态类TestHelloWorld扩展了HelloWorld{
公共TestHelloWorld(){
超级();
}
@凌驾
公共无效开始(阶段primaryStage)引发IOException{
超级启动(初级阶段);
stageFuture.set(初级阶段);
}
}
@以前
@凌驾
public void setupStage()可丢弃{
assumeTrue(!UserInputDetector.instance.hasDetectedUserInput());
FXTestUtils.launchApp(TestHelloWorld.class);//您可以在此处添加开始参数
试一试{
stage=targetWindow(stageFuture.get(25,TimeUnit.SECONDS));
FXTestUtils.bringToFront(阶段);
}捕获(例外e){
抛出新的RuntimeException(“无法显示阶段”,e);
}
}
@凌驾
受保护的父getRootNode(){
return stage.getScene().getRoot();
}
//在此处添加您的测试
}
谢谢。我将StackPane
创建、按钮操作侦听器等移动到构造函数中,并将StackPane
作为类的私有字段,以便它可用于getRootNode()
,同时将primaryStage
的任何代码保留在start()中
它现在正在工作。您能提供额外的代码,在文本字段中写入内容,然后再次读出或类似内容吗?
public class HelloWorldGuiTest extends GuiTest {
private static final SettableFuture<Stage> stageFuture = SettableFuture.create();
protected static class TestHelloWorld extends HelloWorld {
public TestHelloWorld() {
super();
}
@Override
public void start(Stage primaryStage) throws IOException {
super.start(primaryStage);
stageFuture.set(primaryStage);
}
}
@Before
@Override
public void setupStage() throws Throwable {
assumeTrue(!UserInputDetector.instance.hasDetectedUserInput());
FXTestUtils.launchApp(TestHelloWorld.class); // You can add start parameters here
try {
stage = targetWindow(stageFuture.get(25, TimeUnit.SECONDS));
FXTestUtils.bringToFront(stage);
} catch (Exception e) {
throw new RuntimeException("Unable to show stage", e);
}
}
@Override
protected Parent getRootNode() {
return stage.getScene().getRoot();
}
// Add your tests here
}