Custom source set in Gradle imported to IntelliJ 14 - intellij-idea

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

Related

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

Setting Up a Multiplatform Project

considering Kotlin 1.2 introduced kotlin-platform-common I'm trying to build my first common .class file, so I did the below:
main.kt:
package hello
fun main() {
println("kotlin!")
}
gradle.build:
group 'h'
version 'prn'
buildscript {
ext.kotlin_version = '1.2.0'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin-platform-common'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
}
sourceSets {
main.kotlin.srcDirs += 'src/kotlin'
main.resources.srcDirs += 'src/resources'
}
jar {
manifest {
attributes 'Main-Class': 'hello.MainKt'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
Then I run gradle build
Q1- I coud not find any .class file generated? how to get it generated and where should I find it?
Q2- I got a .jar file generated, but once I tried to run it, I got an error:
Error: Could not find or load main class hello.MainKt
I tried to run it using the below 2 option, but got the same error for bot:
Option 1:
kotlin -cp <filename>.jar hello.MainKt
Option 2:
java -jar <filename>.jar
Project structure, and errors are as in this pic below:
With Kotlin 1.2, common modules don't generate binaries (like .class files), only metadata files. This is true even if you don't use the expect keyword anywhere.
So you have to create another module which includes something like this:
apply plugin: 'kotlin-platform-jvm'
The JVM modules will also need an expectedBy entry in dependencies for your common module. Plus you'll probably want a corresponding JS module of course.
It's probably best to let IntelliJ create the whole multiplatform project for you and then edit the Gradle files to suit, but this page lists the manual steps: https://kotlinlang.org/docs/reference/multiplatform.html#setting-up-a-multiplatform-project

How do i invoke cucumber test project with gradle?

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

How to run build.gradle with Sikuli integrated into the project?

I am using Sikuli in my project to handle some flash buttons. It's working fine while running scripts locally. The issue is that when I need to run the build.gradle, I need to have the Sikuli dependency in build.gradle. That is how I have written build.gradle. When I run the build, I get this error:
What went wrong: Could not resolve all dependencies for configuration ':compile'.
Could not find com.googlecode.javacpp:javacpp:0.1. Required by:
:new_qa_automation:1.0 > org.sikuli:sikuli-api:1.0.2 > org.sikuli:sikuli-c ore:1.0.1
Could not find com.googlecode.javacv:javacv:0.1. Required by:
:new_qa_automation:1.0 > org.sikuli:sikuli-api:1.0.2 > org.sikuli:sikuli-c ore:1.0.1
Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED.
Here is my build.gradle file
apply plugin: 'java' version = '1.0' apply plugin: 'project-report'
repositories { mavenCentral() maven { url
"http://repo.springsource.org/release" url
"http://oss.sonatype.org/content/groups/public/" } }
sourceCompatibility = 1.6 targetCompatibility = 1.6
configurations { cucumberRuntime { extendsFrom testRuntime } }
task test(overwrite: true) {
dependsOn assemble, processTestResources, compileTestJava
doLast {
javaexec {
main = "cucumber.api.cli.Main"
classpath = configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output
//some args
systemProperties System.properties
}
} }
dependencies { compile 'org.seleniumhq.selenium:selenium-java:2.32.+'
compile 'org.apache.commons:commons-lang3:3.1' compile
'org.springframework:spring-context:3.2.3.RELEASE'
compile group: 'org.sikuli', name: 'sikuli-api', version: '1.0.+' compile group: 'commons-collections', name: 'commons-collections',
version: '3.+'
testCompile 'info.cukes:cucumber-java:1.1.2'
testCompile 'info.cukes:cucumber-spring:1.1.2'
testCompile 'info.cukes:cucumber-junit:1.1.2'
testCompile 'junit:junit:4.11' testCompile 'org.easytesting:fest-assert-core:2.0+'
}
Edit:
I added the URL for the Maven repositry. Now the error has changed to
ePage.java:9: error: package org.sikuli.script does not exist
import org.sikuli.script.FindFailed;
sikuli-script.jar in Sikuli IDE project not provide in any repository so you must use it like a 3rd party jar
see:
"Mavan's central repository will not answer on any Sikuli stuff" https://answers.launchpad.net/sikuli/+question/185713
"Gradle: Make a 3rd party jar available to local gradle repository" Gradle: Make a 3rd party jar available to local gradle repository
The Sikuli code base appears to be fragmented. It's quite confusing; I know of 3 different sets of Java bindings. (one, two, three)
I think the one you're pulling with Maven is this: http://code.google.com/p/sikuli-api/
If so, org.sikuli.script is not the right import. You don't include your code to show me what you're trying to do with Sikuli, but most of the things you'd want to import are somewhere under org.sikuli.api.
Just download the sikulix jar and mention it in build.gradle
eg: compile files('C:\Users\vedavyasa\Documents\jar\sikulixapi.jar')

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')
}