0

Why is my Spock test not executed and I get zero test results when I execute:

./gradlew clean test

with my TestFX Spock Gradle Project with Openjdk 11?


Here's the zero test results: enter image description here


My Spock test class gets compiled OK but not executed.

Here's my console:

Working Directory: /home/~/EclipseProjects/gradleTestfxSpock
Gradle user home: /home/~/.gradle
Gradle Distribution: Gradle wrapper from target build
Gradle Version: 5.0
Java Home: /usr/lib/jvm/jdk-11.0.2+9
JVM Arguments: None
Program Arguments: None
Build Scans Enabled: false
Offline Mode Enabled: false
Gradle Tasks: clean test


> Configure project :
Found module name 'mtd'

> Task :clean
> Task :compileJava
> Task :compileGroovy NO-SOURCE
> Task :processResources
> Task :classes
> Task :compileTestJava NO-SOURCE
> Task :compileTestGroovy
> Task :processTestResources
> Task :testClasses
> Task :test

BUILD SUCCESSFUL in 6s
6 actionable tasks: 6 executed

Here's my build.gradle:

plugins {    
    id 'org.openjfx.javafxplugin' version '0.0.7'   
    id 'application'
    id 'groovy'
}

mainClassName = 'mtd/gradleTestfxSpock.Main'

sourceCompatibility = 11
targetCompatibility = 11

repositories {  
    jcenter()   
}

dependencies {
    implementation 'org.testfx:testfx-spock:4.0.15-alpha'
    testCompile    'org.testfx:testfx-core:4.0.15-alpha'        

    testCompile (group: 'org.spockframework', name: 'spock-core', version: '1.3-groovy-2.5')
    testCompile ('org.codehaus.groovy:groovy-all:2.5.6')
    testRuntime(
        'com.athaydes:spock-reports:1.2.7',
        'cglib:cglib-nodep:3.2.4'
    )
}

javafx {
    version = "11.0.2"
    modules = [ 'javafx.controls',
            'javafx.fxml',
            'javafx.web'
          ]
}

compileJava {
    doFirst {
        options.compilerArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.controls',
                '--add-modules', 'javafx.fxml',
                '--add-modules', 'javafx.web'
        ]
    }
}

test {
    doFirst {
        jvmArgs = [
            '--module-path', classpath.asPath,
            '--add-modules', 'ALL-MODULE-PATH',
            '--add-exports', 'javafx.graphics/com.sun.javafx.application=org.testfx'            
        ]
    }
}

Here's my module-info.java:

module mtd {

requires javafx.controls;
requires javafx.fxml;
requires transitive javafx.graphics;
requires javafx.web;

requires org.testfx;
requires testfx.spock;  

opens gradleTestfxSpock to javafx.graphics;

exports gradleTestfxSpock;      
}

Here's my Spock test code:

package gradleTestfxSpock;

import org.testfx.framework.spock.ApplicationSpec;
import javafx.stage.Stage


public class MainTest extends ApplicationSpec{


    def "Main Test 01"() {              
        expect:     
        println("you are in Main test 01");     
    }

    @Override
    public void start(Stage arg0) throws Exception {
        // TODO Auto-generated method stub      
    }


}

Here's my JavaFX code:

package gradleTestfxSpock;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{        
        Parent root = FXMLLoader.load(getClass().getResource("/fxml/sample.fxml"));        
        primaryStage.setTitle("Hello World");
    primaryStage.setScene(new Scene(root, 300, 275));
    primaryStage.show();
    }


    public static void main(String[] args) {
    launch(args);
    }
}

and controller:

package gradleTestfxSpock;
public class Controller {
}

Here's my eclipse gradle project structure:

enter image description here


In other eclipse gradle projects I have successfully executed a TestFX Junit4 test without Spock:

enter image description here


and separately I have successfully executed the same Spock Test without TestFX and without JUnit:

enter image description here


I did notice some warnings on this Spock test:

Working Directory: /home/~/EclipseProjects/gradleSpock
Gradle user home: /home/~/.gradle
Gradle Distribution: Gradle wrapper from target build
Gradle Version: 5.0
Java Home: /usr/lib/jvm/jdk-11.0.2+9
JVM Arguments: None
Program Arguments: None
Build Scans Enabled: false
Offline Mode Enabled: false
Gradle Tasks: clean test

> Task :clean
> Task :compileJava
> Task :compileGroovy NO-SOURCE
> Task :processResources NO-SOURCE
> Task :classes
> Task :compileTestJava NO-SOURCE
> Task :compileTestGroovy
> Task :processTestResources NO-SOURCE
> Task :testClasses

> Task :test
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/home/dm/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.6/6936e700f0fb1b50bac0698ada4347a769d40199/groovy-2.5.6.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

BUILD SUCCESSFUL in 9s
4 actionable tasks: 4 executed

Conclusion

If TestFX with JUnit works, and Spock alone works, but TestFX with Spock doesn't work then is there something wrong with configuring:

'org.testfx:testfx-spock:4.0.15-alpha'

Any ideas or help greatly appreciated.

ps Forgot to say that I also created the TestFX/Spock project in Netbeans duplicating the eclipse project, and I got the same result!


More Tests

More combinations of testing following Leonard Bruenings very good suggestions in comments below unfortunately didn't work.

My amended module-info.java looks like:

module mtd {

requires javafx.controls;
requires javafx.fxml;
requires transitive javafx.graphics;
requires javafx.web;

requires org.testfx.junit;
requires org.testfx;
requires testfx.spock;
requires spock.core;
requires junit;

opens gradleTestfxSpock to javafx.graphics, org.testfx, testfx.spock, spock.core, junit, org.testfx.junit;

exports gradleTestfxSpock;      
}

And I added this to my gradle.build dependencies just in case:

implementation 'org.testfx:testfx-junit:4.0.15-alpha'

Still no joy...

David Miller
  • 694
  • 6
  • 7
  • I haven't used spock with module path yet, but could it be that you need to open your module to spock and junit? – Leonard Brünings Apr 29 '19 at 19:30
  • Great thoughts Leonard - thanks - make sense. Unfortunately didn't work. Please see "More Tests" edits in my main posting. – David Miller Apr 29 '19 at 21:07
  • Thinking about it I got Spock to work without TestFX in a gradle project with Openjdk11, and I didn't need to open my project. Here's my module.info: module mtd { exports gradleSpock; } – David Miller Apr 29 '19 at 21:18
  • Have you checked the Java 11 section here https://github.com/TestFX/TestFX you need to include additional libraries. – Leonard Brünings Apr 29 '19 at 21:54
  • Yes I had checked this TestFX Java 11 section carefully. Apart from the TestFX dependencies it just stipulates adding the JavaFX modules which became separate in Java 11 - these are just the standard things to do with JavaFX 11 modules with Java 11 which I have included in my build.gradle above. Unless I have missed anything else here of course. Thanks very much for pointing this out. – David Miller Apr 29 '19 at 23:29

2 Answers2

0

Solution

I found that this plugin was the problem and was stopping successful execution of my Spock test:

`plugins {    
    id 'org.openjfx.javafxplugin' version '0.0.7'
 }`

When I removed it from my build.gradle my TestFX Spock test worked OK.

With this reworked build.gradle and module-info.java I can successfully execute my Spock test:

plugins { 
    id 'application'
    id 'groovy'
}

ext {
    moduleName = "mtd"
    mainQualifiedClassName = "gradleTestfxSpock.Main"
}

application {
    mainClassName = "$moduleName/$mainQualifiedClassName"
}

sourceCompatibility = 11
targetCompatibility = 11

repositories {  
    jcenter()   
}

dependencies {
    implementation("org.openjfx:javafx-fxml:11:linux")
    implementation("org.openjfx:javafx-web:11:linux")
    implementation("org.openjfx:javafx-media:11:linux")
    implementation("org.openjfx:javafx-base:11:linux")
    implementation("org.openjfx:javafx-graphics:11:linux")
    implementation("org.openjfx:javafx-controls:11:linux")

    testImplementation ('org.testfx:testfx-spock:4.0.15-alpha')
    testImplementation ('org.testfx:testfx-core:4.0.15-alpha')

    testImplementation (group: 'org.spockframework', name: 'spock-core', version: '1.3-groovy-2.5')
    testImplementation ('org.codehaus.groovy:groovy-all:2.5.6')

    testRuntimeOnly (
            'com.athaydes:spock-reports:1.2.7',
            'cglib:cglib-nodep:3.2.4'
    )
}


compileJava {
    doFirst {
       options.compilerArgs = [
            '--module-path', classpath.asPath,
            '--add-modules', 'javafx.controls',
            '--add-modules', 'javafx.fxml',
            '--add-modules', 'javafx.web'
       ]
    }
}

run {
    doFirst {
        jvmArgs = [
                '--module-path', classpath.asPath,
                '--patch-module', "$moduleName=" + files(sourceSets.main.output.resourcesDir).asPath,
                '--module', mainClassName
        ]   
    }
}

I needed to add into the run section of the build.gradle:

  1. '--module', mainClassName

    -so that the mainClassName can be found

  2. '--patch-module', "$moduleName=" + files(sourceSets.main.output.resourcesDir).asPath

    -to provide access to resource files eg getClass().getResource("/fxml/sample.fxml")


module mtd {

requires javafx.controls;
requires javafx.fxml;
requires transitive javafx.graphics;
requires javafx.web;


exports gradleTestfxSpock;
}
David Miller
  • 694
  • 6
  • 7
0

I'm no expert in any of this, which is probably why it's taken me ages and ages to get to this point, but FWIW I thought I might just mention that I have managed to get it working: by "it" I mean: Java 11, JavaFX, TestFX-Spock, and using the javafxplugin. One guy who helped me, José Pereda, appears to recommend using it if you can. So I just thought I'd show my files stripped down to the bare minimum. There's no module-info.java, and I'm using Groovy for my app code as well as for Spock and Gradle.

(stripped-down) build.gradle:

plugins {
    id 'java-library'
    id 'groovy'
    id 'eclipse'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
}
repositories {
    mavenCentral()
}
dependencies {
    api 'org.apache.commons:commons-math3:3.6.1'
    implementation 'com.google.guava:guava:27.0.1-jre'
    // although not using JUnit I think it's best to leave this line
    // (included at start by Gradle):
    testImplementation 'junit:junit:4.12'
    implementation 'org.codehaus.groovy:groovy-all:2.5.8'
    testImplementation 'org.spockframework:spock-core:1.2-groovy-2.5'
    testImplementation 'org.testfx:testfx-spock:4.0.15-alpha'
}
mainClassName = 'core.App'
group 'Project'
version '1.0'
sourceCompatibility = 11
javafx {
    version = "13"
    modules = [ "javafx.controls", "javafx.fxml" ]
}

src/main/groovy/core/main.groovy:

package core
// (imports omitted)
public class App extends Application {
    void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"))
        primaryStage.title = "Hello World"
        primaryStage.scene = new Scene(root, 300, 275)
        primaryStage.show()
    }
    def main(String[] args) {
        launch( App.class, args)
    }
}

class Controller {
    @FXML
    TextField inputField
    @FXML
    Label label
    @FXML
    Button applyButton
    public void applyButtonClicked () {
        label.text = inputField.text
    }
}

src/test/groovy/core/test.groovy:

package core
// (imports omitted)
class FuncSpec extends ApplicationSpec {
    void init() throws Exception {
        FxToolkit.registerStage { new Stage() }
    }
    def cleanup() {
        FxToolkit.hideStage()
        // as explained for org.testfx.robot.KeyboardRobot, passing an
        // empty array of the appropriate type releases all keys/mouse buttons
        // NB this is how you create an empty typed array in Groovy
        release(new KeyCode[0])
        release(new MouseButton[0])
    }
    @Override
    public void start(Stage stage) throws Exception {
        Parent mainNode = FXMLLoader.load( App.class.getResource("sample.fxml"))
        stage.scene = new Scene(mainNode)
        stage.show()
        stage.toFront()
    }
    def "test English input"(){
        when: 
        Label label = lookup("#label").query()
        clickOn("#inputField")
        write("This is a test!")
        clickOn("#applyButton")

        then:
        label.text == "This is a test!"
    }
}

src/main/resources/core/sample.fxml // NB note inclusion of "core" (package name)

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane alignment="center" hgap="10" vgap="10"
    xmlns:fx="http://javafx.com/fxml/1"
    xmlns="http://javafx.com/javafx/8.0.111"
    fx:controller="core.Controller">
    <children>
        <TextField layoutX="15.0" layoutY="25.0" fx:id="inputField" />
        <Label layoutX="15.0" layoutY="84.0" text="TEXT GOES HERE"
            fx:id="label" />
        <Button layoutX="124.0" layoutY="160.0" mnemonicParsing="false"
            text="Apply" onAction="#applyButtonClicked" fx:id="applyButton" />
    </children>
</GridPane>
mike rodent
  • 14,126
  • 11
  • 103
  • 157
  • Thanks for the reference, but let me clarify that I'm not the author of the plugin. I have contributed to it though, and I do really recommend its use for any JavaFX 11+ project with Gradle. Issues with the plugin can be reported [here](https://github.com/openjfx/javafx-gradle-plugin/issues). – José Pereda Sep 29 '19 at 19:48
  • Thank you very much for your posting - that's a very helpful reference. I notice 2 differences from mine: you specify javafx { version = "13" } and I have version = "11.0.2" and you don't have a module-info.java as I do. Don't know whether these are significant. I'll follow your lead and retest when I come back to this. – David Miller Sep 30 '19 at 10:40