Configure Jacoco with gradle and kotlin DSL - gradle

I'm trying to configure Jacoco to exclude some classes from analysis but can't find any working example :(
I found some samples with afterEvaluate but no success

src/main/java/org/example/A.java:
package org.example;
class A {
}
src/main/java/org/example/B.java:
package org.example;
class B {
}
src/test/java/org/example/ExampleTest.java:
package org.example;
public class ExampleTest {
#org.junit.Test
public void test() {
new A();
new B();
}
}
build.gradle.kts:
plugins {
java
jacoco
}
repositories {
mavenCentral()
}
dependencies {
testCompile("junit:junit:4.12")
}
using Gradle 5.4.1 execution of gradle test jacocoTestReport produces following report
after addition to build.gradle.kts
tasks.withType<JacocoReport> {
classDirectories.setFrom(
sourceSets.main.get().output.asFileTree.matching {
exclude("org/example/B.class")
}
)
}
execution of the same command produces following report

Just to add to #Godin's awesome answer:
The way #Godin explained it, you would have to run gradle test jacocoTestReport which isn't bad but If you want jacoco to run when you run just with gradle test add this to your build.gralde.kts:
tasks.test {
finalizedBy("jacocoTestReport")
doLast {
println("View code coverage at:")
println("file://$buildDir/reports/jacoco/test/html/index.html")
}
}

I've managed to exclude this way:
tasks.jacocoTestReport {
classDirectories.setFrom(
files(classDirectories.files.map {
fileTree(it) {
exclude(
"com/example/integration/**",
"com/example/application/*Ext*"
)
}
})
)
}
Taken from here

Related

Received a failure event for test with unknown id, Gradle, Junit4, SystemRules

When running gradle test I receive an error
Caused by: java.lang.IllegalArgumentException: Received a failure event for test with unknown id '16.3'. Registered test ids: '[16.1, 16.2, :app:test]
This error only occurs when tests include functionality added by system-rules. For example
#Test
void sysOutTest() {
System.out.print("hello world");
assertEquals("hello world", systemOutRule.getLog());
}
My build.gradle file looks like this:
plugins {
id 'application'
id 'jacoco'
}
repositories {
jcenter()
}
dependencies {
testImplementation 'com.github.stefanbirkner:system-rules:1.19.0'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.1.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.1.0'
testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.1.0'
}
application {
// Define the main class for the application.
mainClass = 'package.App'
}
test {
useJUnitPlatform()
//scanForTestClasses false (This was in here and is commented out as originaly gradle was not detecting tests that were in the style of Junit4)
finalizedBy jacocoTestReport
}
run{
standardInput = System.in
}
jacocoTestReport {
reports {
html.enabled = true
csv.enabled = true
}
}
sourceSets {
test {
java {
srcDir 'test'
}
}
main {
java {
srcDir 'main'
}
}
}
To be clear, tests work fine when the file has no tests that use SystemRules.
I've (stupidly) already written all my tests using SystemRules, so I would prefer to find a way to make it work instead of starting from scratch.
Thanks for any help
I just needed to put public before my tests. All the other tests that didn't use System rules had public.
#Test
public void sysOutTest() {
System.out.print("hello world");
assertEquals("hello world", systemOutRule.getLog());
}

execute JavaExec task using gradle kotlin dsl

I've created simple build.gradle.kts file
group = "com.lapots.breed"
version = "1.0-SNAPSHOT"
plugins { java }
java { sourceCompatibility = JavaVersion.VERSION_1_8 }
repositories { mavenCentral() }
dependencies {}
task<JavaExec>("execute") {
main = "com.lapots.breed.Application"
classpath = java.sourceSets["main"].runtimeClasspath
}
In src/main/java/com.lapots.breed I created Application class with main method
package com.lapots.breed;
public class Application {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
But when I try to execute execute tasks it fails with the error that task doesn't exist. Also when I list all the available tasks using gradlew tasks it doesn't show execute task at all.
What is the problem?
The following build script should work (Gradle 4.10.2, Kotlin DSL 1.0-rc-6):
group = "com.lapots.breed"
version = "1.0-SNAPSHOT"
plugins {
java
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
}
repositories {
mavenCentral()
}
task("execute", JavaExec::class) {
main = "com.lapots.breed.Application"
classpath = sourceSets["main"].runtimeClasspath
}
According the not-listed task - from certain version, Gradle doesn't show custom tasks which don't have assigned AbstractTask.group. You can either list them via gradle tasks --all, or set the group property on the given task(s), e.g.:
task("execute", JavaExec::class) {
group = "myCustomTasks"
main = "com.lapots.breed.Application"
classpath = sourceSets["main"].runtimeClasspath
}

Why won't my Groovy main class execute from the built jar?

I'm trying to build an executable JAR with a Groovy main class. I can get a Java main class to run exactly as expected, but the Groovy equivalent just isn't found and won't run.
In src/main/groovy/foo/Test.groovy:
package foo
public class Test { // (Yes, the public keywords here and below are redundant)
public static void main(String[] args) {
println "groovy world"
}
}
In src/main/groovy/foo/Test2.java:
package foo;
public class Test2 {
public static void main(String[] args) {
System.out.println("java world");
}
}
Gradle file:
plugins {
id 'java'
id 'groovy'
id 'application'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
mainClassName = 'foo.Test'
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.7'
}
jar {
manifest {
attributes 'Main-Class': mainClassName
}
}
I build a JAR:
$ ./gradlew build
And try and run it (overriding the manifest Main-Class):
$ java -cp build/libs/test-groovy-main.jar foo.Test2
java world
$ java -cp build/libs/test-groovy-main.jar foo.Test
Error: Could not find or load main class foo.Test
If I turn on verbose output whilst doing this, in the second case I see "Loaded foo.Test2", but no "Loaded foo.Test" in the first.
I had thought that Groovy source compiles to plain java classes, and indeed decompiling the Test.class file I can see a public static main(String...) method in a public Test class. What am I doing wrong?
I'm using Gradle 2.6, Java 1.8.0 and Groovy 2.4.7 on Ubuntu 16.04.
I have the test case in version control here:
https://github.com/wu-lee/test-groovy-main
Adding of from section worked for me:
jar {
manifest {
attributes 'Main-Class': mainClassName
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
it puts the org.codehaus.groovy:groovy-all:2.4.7 dependency to your jar.
UPD
Created a pull-request https://github.com/wu-lee/test-groovy-main/pull/1

Is there a concept of test suites in Gradle/Spock land?

Groovy/Gradle project here that uses Spock for unit testing.
Does Spock and/or Gradle support test suites or named sets of tests? For reasons outside the scope of this question, there are certain Spock tests (Specifications) that the CI server just can't run.
So it would be great to divide all my app's Spock tests into two groups:
"ci-tests"; and
"local-only-tests"
And then perhaps we could invoke them via:
./gradlew test --suite ci-tests
etc. Is this possible? If so, what does the setup/config look like?
You can annotate the tests that should not run in your CI server with the Spock annotation #IgnoreIf( ).
See the documentation here: https://spockframework.github.io/spock/docs/1.0/extensions.html#_ignoreif
All you need to do is let the CI server set an environment variable, and exclude the test class if that variable is set.
Spock even have properties inside the closure to make it easy:
#IgnoreIf({ sys.isCiServer })
I would set up a submodule my-app-ci-test, with the following in build.gradle:
test {
enabled = false
}
task functionalTest(type: Test) {
}
Then you place your tests in src/test/groovy and run ./gradlew functionalTest.
Alternatively, you could include them in the same module and configure the test and functionalTest tasks with includes / excludes
test {
exclude '**/*FunctionalTest.groovy'
}
task functionalTest(type: Test) {
include '**/*FunctionalTest.groovy'
}
If you use Junit test-runner for Spock tests, you may use #Category annotation. Example by article and official documentation:
public interface FastTests {
}
public interface SlowTests {
}
public interface SmokeTests
}
public static class A {
#Test
public void a() {
fail();
}
#Category(SlowTests.class)
#Test
public void b() {
}
#Category({FastTests.class, SmokeTests.class})
#Test
public void c() {
}
}
#Category({SlowTests.class, FastTests.class})
public static class B {
#Test
public void d() {
}
}
test {
useJUnit {
includeCategories 'package.FastTests'
}
testLogging {
showStandardStreams = true
}
}
You can use the following SpockConfiguration.groovy to allow passing include/exclude via system properties
runner {
exclude {
System.properties['spock.exclude.annotations']
?.split(',')
*.trim()
?.each {
try {
annotation Class.forName(it)
println "Excluding ${it}"
} catch (ClassNotFoundException e) {
println "Can't load ${it}: ${e.message}"
}
}
}
include {
System.properties['spock.include.annotations']
?.split(',')
*.trim()
?.each {
try {
annotation Class.forName(it)
println "Including ${it}"
} catch (ClassNotFoundException e) {
println "Can't load ${it}: ${e.message}"
}
}
}
}

Not able to execute Jbehave with Gradle using Serenity Framewrok

I am using Serenity - JBehave framework. After creation of sample script, I am able to execute Junit runner class from eClipse however when I am trying to execute any of the below command from command prompt it is giving me error.
$gradle clean test aggregate
$gradle clean test
$gradle clean build
The error message is same in all cases, as below:
org.gradle.TestRunnerClass > initializationError FAILED
java.lang.RuntimeException
Caused by: java.lang.RuntimeException
Caused by: java.lang.IllegalArgumentException
Caused by: java.lang.ClassNotFoundException
1 test completed, 1 failed
:test FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///C:/$ /build/reports/tests/index.html
Below are the details:
Test Runner class:
package org.gradle;
import net.serenitybdd.jbehave.SerenityStories;
public class TestRunnerClass extends SerenityStories{}
Sample Step Definition class:
package org.gradle.stepDef;
import net.thucydides.core.annotations.Step;
import net.thucydides.core.annotations.Steps;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
public class StepDefSticky {
#Given("User is on Sticky note home page")
public void givenUserIsOnStickyNoteHomePage() {
System.out.println("I am in Given");
}
#When("User clicks on Add Note button")
public void whenUserClicksOnAddNoteButton() {
System.out.println("I am in When");
}
#Then("Sticky note pop up should get open")
public void thenStickyNotePopUpShouldGetOpen() {
System.out.println("I am in Then");
}
}
Please see the package structure carefully.
Below is the build.gradle I am using
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'net.serenity-bdd.aggregator'
apply plugin: 'com.jfrog.bintray'
sourceCompatibility = 1.8
version = '1.0'
def poiVersion = "3.10.1"
repositories {
maven { url "repoUrl" }
}
buildscript {
repositories {
maven { url "repoURL" }
}
dependencies {
classpath("net.serenity-bdd:serenity-gradle-plugin:1.0.47")
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:0.6'
classpath 'org.ajoberstar:gradle-git:0.12.0'
}
}
ext {
bintrayBaseUrl = 'https://api.bintray.com/maven'
bintrayRepository = 'maven'
bintrayPackage = 'serenity-cucumber'
projectDescription = 'Serenity Cucumber integration'
if (!project.hasProperty("bintrayUsername")) {
bintrayUsername = 'wakaleo'
}
if (!project.hasProperty("bintrayApiKey")) {
bintrayApiKey = ''
}
serenityCoreVersion = '1.0.47'
cucumberJVMVersion = '1.2.2'
}
dependencies {
testCompile('junit:junit:4.11')
testCompile('org.assertj:assertj-core:1.7.0')
testCompile('org.slf4j:slf4j-simple:1.7.7')
//JBehave jar files
testCompile 'net.serenity-bdd:core:1.0.47'
testCompile 'net.serenity-bdd:serenity-jbehave:1.0.21'
testCompile 'net.serenity-bdd:serenity-junit:1.0.47'
// Apache POI plugin for excel read
compile "org.apache.poi:poi:${poiVersion}"
compile "org.apache.poi:poi-ooxml:${poiVersion}"
compile "org.apache.poi:ooxml-schemas:1.1"
}
gradle.startParameter.continueOnFailure = true
uploadArchives {
repositories { flatDir { dirs 'repos' } }
}
task wrapper(type: Wrapper) { gradleVersion = '2.3' }
I have stored the .story file under the src/test/resources package.
Please help me to understand where I am making mistake. Thanks for your help on this.
Enable standard out and standard error in your build.gradle file:
test {
testLogging {
showStandardStreams = true
}
}
And to make sure all your stories run, add a TestSuite class:
#RunWith(Suite.class)
#SuiteClasses({ Story1.class, Story2.class})
public class TestSuite { }
Note: Story1 & Story2 are the names of the test runners to match a JBehave Gherkin files named Story1.story & Story2.story & step files names Story1Steps.java & Story2Steps.java according to Serenity naming conventions.

Resources