Mateusz Chrzaszcz
Mateusz Chrzaszcz

Reputation: 1280

Create a Groovy executable jar with Spock test set as to be executed

I want to create jar with two groovy files, AppLogic.groovy which consists of two few groovy classes and another file, AppSpec that has Spock test suite and I would like to have this Spock class executed (set as executable). How can I create such jar with all dependencies? I found sth similar for jUnit here: how to export (JUnit) test suite as executable jar but could not adapt it for my needs.

I use gradle for build, here is my build.gradle file:

group 'someGroup'
version '1.0'

apply plugin: 'groovy'
apply plugin: 'java'
apply plugin:'application'

sourceCompatibility = 1.7

repositories {

//some repos here

maven { url "http://repo.maven.apache.org/maven2" }
}

dependencies {
//some dependencies here
}

I was browsing around and found SpockRuntime, but I do not know if and how I can use it to achive my goal.

Upvotes: 3

Views: 2122

Answers (2)

Farrukh Najmi
Farrukh Najmi

Reputation: 5316

I do not advise using the EmbeddedSpecRunner from spock implementation as described in accepted answer.

This is what I found to work reliably with gradle 4.9. The basic approach is to use:

  1. The gradle application plugin to create a single tarfile with all testRuntimeClasspath dependencies and shell scripts to run the spock tests
  2. The gradle maven-publish plugin to publish the tar file as an artifact to your maven repo (in my case nexus)

The build.gradle file looks like this:

apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'maven-publish'
apply plugin: 'application'

mainClassName = 'org.junit.runner.JUnitCore' // The junit 4 test runner class
applicationName = 'run-tests-cli'  // Feel free to change

repositories {
    ...
}

dependencies {
    ...

    testImplementation "org.codehaus.groovy:groovy-all:${groovyVersion}"
    testImplementation "org.spockframework:spock-core:${spockVersion}"

}

// Package compiled spock / junit tests to <artifact>-test-<version>.jar
task testJar(type: Jar) {
    classifier = 'tests'
    from sourceSets.test.output.classesDirs
}

// Copy all testRuntimeClasspath dependencies to libs folder
task copyToLibs(type: Copy) {
    from configurations.testRuntimeClasspath
    into "$buildDir/libs"
}

// Make sure test jar is copied
copyToLibs.dependsOn('testJar')

// Make sure platform-specific shell scripts are created after copyToLibs
startScripts.dependsOn(copyToLibs)

// Configure what goes into the tar / zip distribution file created by gradle distribution plugin assembleDist task
distributions {
    main {
        contents {
            // Include test jar
            from(testJar) {
                into "lib"
            }
            // Include all dependencies from testRuntimeClasspath
            from(copyToLibs) {
                into "lib"
            }
        }
    }
}

startScripts {
    // Ensure ethat all testRuntimeClasspath dependencies are in classpath used by shell scripts
    classpath = project.tasks['testJar'].outputs.files + project.configurations.testRuntimeClasspath
}

publishing {
    repositories {
        maven {
            def releasesRepoUrl = "https://nexus.yourcompany.com/repository/maven-releases/"
            def snapshotsRepoUrl = "https://nexus.yourcompany.com/repository/maven-snapshots/"
            url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
            credentials {
                username = rootProject.getProperty('NEXUS_USERNAME')
                password = rootProject.getProperty('NEXUS_PASSWORD')
            }
        }
    }
    publications {
        maven(MavenPublication) {
            groupId = 'com.yourgroupId'
            version = "${rootProject.getVersion()}"
        }
        TestJar(MavenPublication) {
            artifact(testJar)
        }
        RunTestsCliTar(MavenPublication) {
            artifact(distTar)
            artifactId "${applicationName}"
        }
    }
}

Now you can do the following:

  • To build the project (including the tar file) without running test task: gradle -x test clean build
  • To publish artifacts produced by project (including tar file to maven repo - in my case nexus): gradlew -x test publish. Note you will need to provide credentials to upload artifacts to repo. It is good practice to define them (NEXUS_USERNAME, NEXUS_PASSWORD in my example) in ~/.gradle/gradle.properties or specify them via -P options on the gradle command line.

Upvotes: 0

Mateusz Chrzaszcz
Mateusz Chrzaszcz

Reputation: 1280

And the winner is:

static void main(String[] args) {
    EmbeddedSpecRunner embeddedSpecRunner = new EmbeddedSpecRunner()
    embeddedSpecRunner.runClass(MySpec)
}

Upvotes: 6

Related Questions