How do i invoke cucumber test project with gradle? - testing

I am very new to gradle and i am so confused in how to invoke my project so i can run my Cucumber test. What do i do after creating a build.gradle file?
my build.gradle looks like this
apply plugin: 'java'
dependencies {
testCompile 'info.cukes:cucumber-java:1.2.4'
testCompile 'info.cukes:cucumber-junit:1.2.4'
testCompile 'junit:junit:4.12'
}
repositories {
mavenCentral()
}
project.ext {
cucumberVersion = '1.2.4'
junitVersion = '4.11'
}
test {
testLogging.showStandardStreams = true
systemProperties System.getProperties()
}

You create a JUnit class that uses a Cucumber runner to execute Cucumber.
#RunWith(Cucumber.class)
public class RunCukesTest {
}
in your test directory.
I describe it with more details here: http://www.thinkcode.se/blog/2015/01/30/bdd-with-cucumberjvm-at-geecon-tdd-2015
Another option is to start with the Java skeleton project that is available here: https://github.com/cucumber/cucumber-java-skeleton
And then follow the steps outlined in http://www.thinkcode.se/blog/2015/12/26/gradle-and-cucumberjvm

Just to extend Thomas's great answer I want to mention, that if your have your custom TestRunner class for specific suite of tests (like previously mentioned RunCukesTest or e.g. RegressionTestRunner), it is possible to add custom task for running the exact runner:
task runRegressionTests(type: Test) << {
include "RegressionTestRunner.class"
}
And then it is easy to run regression tests by gradle task:
gradle runRegressionTests
If you have a multiple runner classes for different suites (RegressionTestRunner, SanityTestRunner, etc) - it is useful to write a custom pattern for testing task which will recognize and run defined runner class.
E.g.:
runRegressionTests, runSanityTests.

Added the below in build.gradle file
test {
testLogging.showStandardStreams = true
systemProperties System.getProperties()
}
It invoked my cucumber test for gradle clean build

Use Gradle Cucumber JVM Plugin. It works perfectly and has pretty html reports integrated.
https://github.com/commercehub-oss/gradle-cucumber-jvm-plugin

Related

Can I write gradle buildSrc in Kotlin?

I'd like to write my Gradle buildSrc in Kotlin instead of Java, since everything else is Kotlin too.
I've tried .kt files in buildSrc/src/main/kotlin and in buildSrc/src/main/java, but neither will be compiled. IntelliJ does recognize them at least when I put them in /java, but they are not found when running Gradle tasks.
So, how do I make Gradle look at Kotlin build sources?
buildSrcis treated as an included build, and you can use any supported language inside this project, as long as you apply the needed plugins.
Following setup should work :
buildSrc/build.gradle
plugins {
id("org.jetbrains.kotlin.jvm") version "1.3.72"
}
repositories {
mavenCentral()
}
custom task:
buildSrc/src/main/kotlin/tasks/MyKtTask.kt
package tasks
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
open class MyKtTask : DefaultTask() {
#TaskAction
fun execute() {
println("kotlin tasks executed")
}
}
Using the custom task:
build.gradle
task "testKt" (type: tasks.MyKtTask){
doLast{
// do something
}
}

Share Java test helpers classes across different kinds of test modules in Gradle project

I have two kinds of tests: unit and integration tests. I would like to have another one in which I would like to place more complex test cases. Each kind of test is placed in different module.
Bellow I am placing a piece of project structure to make it a little bit more visible
...
---buildSrc
------build.gradle(1)
------gradle.properties
---src
------main (files with production code)
------integration-test
------test (files with unit tests)
------new-test
------build.gradle(2)
...
My goal:
I have already created plenty of test helpers which are placed in integration-test module and I would like to reuse them in new-test module.
This is how looks like my sourceSets in build.gradle(2) file:
sourceSets {
integrationTest {
java.srcDir file('src/integration-test/java')
resources.srcDir file('src/integration-test/resources')
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
}
newTest {
java {
srcDirs 'src/new-test/java'
srcDirs 'src/integration-test/java'
}
resources.srcDir file('/src/new-test/resources')
compileClasspath += main.output + test.output + integrationTest.output
runtimeClasspath += main.output + test.output + integrationTest.output
}
}
And thanks for that (srcDirs 'src/integration-test/java') I am able to use sources from integration-test in new-test module but I have serious doubts if it is a proper way to do that because I am getting a communicate from Intellij:
Path [C:/Repositories/my-project/project/src/integration-test/java] of module [project.newTest] was removed from modules [project.integrationTest]
This is my newTest task from build.gradle(2) file:
task newTest(type: Test) {
useJUnitPlatform() {
excludeEngines "junit-vintage-engine"
}
testClassesDirs = sourceSets.newTest.output.classesDirs
classpath = sourceSets.newtTest.runtimeClasspath
outputs.upToDateWhen { false }
}
And this is my configurations section from build.gradle(2) file:
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
newTestCompile.extendsFrom testCompile
newTestRuntime.extendsFrom testRuntime
}
I have already looked into following tutorials:
Multi-project test dependencies with gradle (I have only one project and here it is shown how to share test
classes between projects)
How to share test classes across Gradle projects?
http://michaelevans.org/blog/2019/09/21/stop-repeating-yourself-sharing-test-code-across-android-modules/ (I can't currently migrate to Gradle 5.6)
Include tests from other module
So what can I do to use test helpers from integration-test module in new-test module? I would like to also separate those helpers classes into separate module and then my new-test and integration-test tasks could take it as a test dependency.
Thanks!
Just create a new project (eg test-lib) for the test helpers/utilities. Put the sources in src/main/java in the test-lib project then depend on test-lib wherever you need it

Integrate Gebish into Gradle

I'm trying to integrate Gebish into Gradle.
I already found this nice tutorial: http://www.gebish.org/manual/0.9.2/build-integrations.html#gradle
The find is that I want to specify the browser with the commandline.
Now I have this code:
def gebVersion = '0.13.1'
def seleniumVersion = '2.51.0'
apply plugin: 'groovy'
repositories {
mavenCentral()
}
dependencies {
testCompile "org.gebish:geb-spock:$gebVersion"
testCompile("org.spockframework:spock-core:1.0-groovy-2.4")
testRuntime "org.seleniumhq.selenium:selenium-support:$seleniumVersion"
/*
// Drivers
testCompile "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion"
testCompile "org.seleniumhq.selenium:selenium-firefox-driver:$seleniumVersion"
*/
}
task firefoxTest(type: Test) {
dependencies {
testCompile "org.seleniumhq.selenium:selenium-firefox-driver:$seleniumVersion"
}
}
task chromeTest(type: Test) {
dependencies {
testCompile "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion"
}
}
test {
systemProperties "geb.build.reportsDir": "$reportsDir/geb"
}
Also I have this big test that is located at src/test/groovy/test.groovy
import geb.Browser
Browser.drive {
go "http://stackoverflow.com"
}
The problem is that if I run gradle with gradlew firefoxTest or gradlew chromeTest it happens nothing and I get the following message:
14:02:03: Executing external task 'chromeTest'...
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava UP-TO-DATE
:compileTestGroovy
:processTestResources UP-TO-DATE
:testClasses
:chromeTest
BUILD SUCCESSFUL
Total time: 2.534 secs
14:02:05: External task execution finished 'chromeTest'.
How can I run my test through the commandline with the specific browser?
Also is it possible to build in Browserstack support?
It looks like you have Gradle set up correctly. However, your big test needs to extend either geb.spock.GebReportingSpec or geb.junit4.GebReportingTest in order to be detected by the test runner as a test. It will then have to contain a test fitting the requirements for either the Spec or the Test. For example, see GebishOrgSpec.groovy and GebishOrgTest.groovy in the Geb Gradle example project.
With regards to running tests using multiple browsers, have a look at the build file of the Geb's example project that uses gradle. Namely at how Geb environment is set here and then used in GebConfig.groovy over here and here.

Custom source set in Gradle imported to IntelliJ 14

I'm trying to get Gradle (2.1) and IntelliJ (14.0.2) to play nicely. Specifically, I have imported a sample Gradle project containing a separate source set for integration tests into IntelliJ.
The project builds fine using Gradle on the command line, and I'm able to run the integration tests successfully. When running inside IntelliJ on the other hand, I have two problems:
1) Compiling inside IntelliJ fails, due to a dependency in the integration test to a third-party library (commons-collections) which fails to resolve.
2) If I remove the dependency above and compile, I'm not able to run the integration test inside IntelliJ. I get the following error message:
No tests found for given includes: [org.gradle.PersonIntegrationTest.canConstructAPersonWithAName]
The file structure looks like this:
src
integration-test
java
resources
main
java
resources
test
java
resources
build.gradle
And build.gradle:
apply plugin: 'java'
repositories {
mavenCentral()
}
sourceSets {
integrationTest {
java.srcDir file('src/integration-test/java')
resources.srcDir file('src/integration-test/resources')
}
}
dependencies {
testCompile 'junit:junit:4.11'
integrationTestCompile 'commons-collections:commons-collections:3.2'
integrationTestCompile sourceSets.main.output
integrationTestCompile configurations.testCompile
integrationTestCompile sourceSets.test.output
integrationTestRuntime configurations.testRuntime
}
task integrationTest(type: Test, dependsOn: jar) {
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
systemProperties['jar.path'] = jar.archivePath
}
check.dependsOn integrationTest
Any ideas on how to make this work would be much appreciated.
The full Gradle sample project is available in the Gradle distribution, under samples/java/withIntegrationTests
You need to tell IDEA to map entries from your integrationTest configuration into your project as TEST dependencies. I am not sure whether you need to add source root directories too. The important part is:
idea {
module {
//and some extra test source dirs
testSourceDirs += file('some-extra-test-dir')
generatedSourceDirs += file('some-extra-source-folder')
scopes.TEST.plus += [ configurations.integrationTest ]
}
}
More is described in http://www.gradle.org/docs/current/dsl/org.gradle.plugins.ide.idea.model.IdeaModule.html
Edits to reflect Daniel's comments: generatedSourceDirs is is Gradle 2.2+.
To set up the test task you will use task like
task integTest(type: Test) {
description = 'Runs the integration tests.'
group = 'verification'
testClassesDir = sourceSets.integTest.output.classesDir
classpath = sourceSets.integTest.runtimeClasspath
reports.junitXml.destination = file("${project.testResultsDir}/$name")
reports.html.destination = file("${project.reporting.baseDir}/$name")
shouldRunAfter test
}
check.dependsOn integTest

Gradle Test Dependency

I have two projects, project A and Project B. Both are written in groovy and use gradle as their build system.
Project A requires project B.
This holds for both the compile and test code.
How can I configure that the test classes of project A have access to the test classes of project B?
You can expose the test classes via a 'tests' configuration and then define a testCompile dependency on that configuration.
I have this block for all java projects, which jars all test code:
task testJar(type: Jar, dependsOn: testClasses) {
baseName = "test-${project.archivesBaseName}"
from sourceSets.test.output
}
configurations {
tests
}
artifacts {
tests testJar
}
Then when I have test code I want to access between projects I use
dependencies {
testCompile project(path: ':aProject', configuration: 'tests')
}
This is for Java; I'm assuming it should work for groovy as well.
This is a simpler solution that doesn't require an intermediate jar file:
dependencies {
...
testCompile project(':aProject').sourceSets.test.output
}
There's more discussion in this question: Multi-project test dependencies with gradle
This works for me (Java)
// use test classes from spring-common as dependency to tests of current module
testCompile files(this.project(':spring-common').sourceSets.test.output)
testCompile files(this.project(':spring-common').sourceSets.test.runtimeClasspath)
// filter dublicated dependency for IDEA export
def isClassesDependency(module) {
(module instanceof org.gradle.plugins.ide.idea.model.ModuleLibrary) && module.classes.iterator()[0].url.toString().contains(rootProject.name)
}
idea {
module {
iml.whenMerged { module ->
module.dependencies.removeAll(module.dependencies.grep{isClassesDependency(it)})
module.dependencies*.exported = true
}
}
}
.....
// and somewhere to include test classes
testRuntime project(":spring-common")
This is now supported as a first class feature in Gradle (since 5.6)
Modules with java or java-library plugins can also include a java-test-fixtures plugin which exposes helper classes and resources to be consumed with testFixtures helper. Benefit of this approach against artifacts and classifiers are:
proper dependency management (implementation/api)
nice separation from test code (separate source set)
no need to filter out test classes to expose only utilities
maintained by Gradle
Example:
:modul:one
modul/one/build.gradle
plugins {
id "java-library" // or "java"
id "java-test-fixtures"
}
dependencies {
testFixturesImplementation("your.jar:dependency:0.0.1")
}
or lazyly just add all dependencies of main implementation configuration:
val testFixturesImplementation by configurations.existing
val implementation by configurations.existing
testFixturesImplementation.get().extendsFrom(implementation.get())
modul/one/src/testFixtures/java/com/example/Helper.java
package com.example;
public class Helper {}
:modul:other
modul/other/build.gradle
plugins {
id "java" // or "java-library"
}
dependencies {
testImplementation(testFixtures(project(":modul:one")))
}
modul/other/src/test/java/com/example/other/SomeTest.java
package com.example.other;
import com.example.Helper;
public class SomeTest {
#Test void f() {
new Helper(); // used from :modul:one's testFixtures
}
}
For more info, see the documentation:
https://docs.gradle.org/current/userguide/java_testing.html#sec:java_test_fixtures
The above solution works, but not for the latest version 1.0-rc3 of Gradle.
task testJar(type: Jar, dependsOn: testClasses) {
baseName = "test-${project.archivesBaseName}"
// in the latest version of Gradle 1.0-rc3
// sourceSets.test.classes no longer works
// It has been replaced with
// sourceSets.test.output
from sourceSets.test.output
}
If ProjectA contains the test code you wish to use in ProjectB and ProjectB wants to use artifacts to include the test code, then ProjectB's build.gradle would look like this:
dependencies {
testCompile("com.example:projecta:1.0.0-SNAPSHOT:tests")
}
Then you need to add an archives command to the artifacts section in ProjectA's build.gradle:
task testsJar(type: Jar, dependsOn: testClasses) {
classifier = 'tests'
from sourceSets.test.output
}
configurations {
tests
}
artifacts {
tests testsJar
archives testsJar
}
jar.finalizedBy(testsJar)
Now when ProjectA's artifacts are published to your artifactory they will include a -tests jar. This -tests jar can then be added as a testCompile dependency for ProjectB (as shown above).
For Gradle 1.5
task testJar(type: Jar, dependsOn: testClasses) {
from sourceSets.test.java
classifier "tests"
}
For Android on the latest gradle version (I'm currently on 2.14.1) you just need to add the below in Project B to get all the test dependencies from Project A.
dependencies {
androidTestComplie project(path: ':ProjectA')
}
dependencies {
testImplementation project(':project_name')
}