Search code examples
javajavafxcucumbertestfx

Using TestFX with Cucumber


I'm trying to use Cucumber with TestFX but cant get any nodes from the application.

I've another class of TestFX that works fine and another class of Cucumber which also works fine. But I'm getting

org.loadui.testfx.exceptions.NoNodesFoundException: No nodes matched 'TextInputControl has text "Can you find this label"'.

TestFXBase :

import javafx.scene.Node;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.stage.Stage;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.testfx.api.FxToolkit;
import org.testfx.framework.junit.ApplicationTest;

import java.util.concurrent.TimeoutException;


public class TestFXBase extends ApplicationTest {

    private static boolean isHeadless = false;

    @BeforeClass
    public static void setupHeadlessMode() {
       if(isHeadless){
            System.setProperty("testfx.robot", "glass");
            System.setProperty("testfx.headless", "true");
            System.setProperty("prism.order", "sw");
            System.setProperty("prism.text", "t2k");
            System.setProperty("java.awt.headless", "true");
        }


    }

    @Before
    public void setUpClass() throws Exception {
        ApplicationTest.launch(Main.class);
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.show();
    }

    @After
    public void afterEachTest() throws TimeoutException {

        FxToolkit.hideStage();
        release(new KeyCode[]{});
        release(new MouseButton[]{});
    }

    /* Helper method to retrieve Java FX GUI Components */
    public <T extends Node> T find (final  String query){
        return (T) lookup(query).queryAll().iterator().next();
    }

}

This is my testfx base class and my cucumber runner and stepdefs extends this.

StepDefs:

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import org.junit.Test;


public class MyStepdefs extends TestFXBase  {
    @Test
    @Given("^That \"([^\"]*)\" Exists$")
    public void thatExists(String arg0) throws Throwable {
        rightClickOn("#rect");
    }
    @Test
    @Then("^Which is \"([^\"]*)\"$")
    public void whichIs(String arg0) throws Throwable {
        System.out.println(arg0);
    }
}

Runner:

import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;


@RunWith(Cucumber.class)
@CucumberOptions(plugin = { "pretty" })
public class MyRunner extends TestFXBase{}

Feature:

Feature: Do label texts exist?

Scenario: Can you find this label text

Given That "Can you find this label" Exists

Then Which is "great"

So, the parameter is passed but TestFX dont start application in my cucumber runner, just tries to find nodes. There is a class that extends TestFXBase and works perfectly. How can I solve this issue?

Edit: My dependencies are

  <dependency>
            <groupId>org.loadui</groupId>
            <artifactId>testFx</artifactId>
            <version>3.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.jfxtras</groupId>
            <artifactId>openjfx-monocle</artifactId>
            <version>1.8.0_20</version>
        </dependency>

        <dependency>
            <groupId>org.testfx</groupId>
            <artifactId>testfx-core</artifactId>
            <version>4.0.6-alpha</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-all</artifactId>
            <version>1.3</version>
        </dependency>
        <dependency>
            <groupId>org.testfx</groupId>
            <artifactId>testfx-junit</artifactId>
            <version>4.0.6-alpha</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>1.2.5</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>1.2.5</version>
            <scope>test</scope>
        </dependency>

Solution

  • Solution here is to move content of setupHeadlessMode and setUpClass methods to TestFXBase class initializer:

    static {
        if (isHeadless) {
            System.setProperty("testfx.robot", "glass");
            System.setProperty("testfx.headless", "true");
            System.setProperty("prism.order", "sw");
            System.setProperty("prism.text", "t2k");
            System.setProperty("java.awt.headless", "true");
        }
    
        try {
            ApplicationTest.launch(Main.class);
        } catch (Exception e) {
            // oh no
        }
    }