I have added the sonar properties into my build.gradle file to upload the project into server when build the project using gradle. below is my build.gradle file.
import org.tmatesoft.svn.core.wc
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'eclipse'
apply plugin: 'findbugs'
apply plugin: 'sonar-runner'
apply plugin: "jacoco"
group = 'com.example.service'
sourceCompatibility = 1.5
version = '1.0'
jar {
manifest {
attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
}
}
findbugs {
// make findbugs non build breaking
ignoreFailures = true
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
compile 'org.apache.commons:commons-lang3:3.1'
compile "org.codehaus.sonar.runner:sonar-runner-api:2.4"
testCompile group: 'junit', name: 'junit', version: '4.+'
}
test {
systemProperties 'property': 'value'
}
sonarRunner {
sonarProperties {
property "sonar.host.url", "http://localhost:9000"
property "sonar.sourceEncoding", "UTF-8"
property "sonar.projectName", "$project.name"
property "sonar.projectKey", "$project.group:$project.name"
property "sonar.projectBaseDir","$project.projectDir"
property "sonar.working.directory","$project.buildDir/sonar"
property "sonar.jacoco.reportPath", "${project.buildDir}/jacoco/test.exec"
}
}
test {
jacoco {
destinationFile = file("$buildDir/jacoco/test.exec")
}
}
uploadArchives {
repositories {
mavenLocal()
}
}
But when I build the project from eclipse nothing happens. No error message in the console, and project is also not uploaded to the sonar server.
Does anyone know how to upload the project into the Sonar Server when building with Gradle?
See couple of my posts and you'll find what you are looking for. Mainly, you have to use:
apply plugin: 'sonar-runner'
Then, I have following config in < YOUR_GRADLE_HOME >/init.d/someglobal.gradle file
allprojects {
apply plugin: 'java'
apply plugin: 'codenarc'
apply plugin: 'pmd'
apply plugin: 'findbugs'
apply plugin: 'checkstyle'
apply plugin: 'jacoco'
apply plugin: 'sonar-runner'
//JavaCompile(Works with recent Gradle versions) or Compile (works with Gradle 1.6)
//tasks.withType(Compile) {
tasks.withType(JavaCompile) {
options.debug = true
options.compilerArgs = ["-g"]
}
//You don't need sourceSets if your project is following Maven/Gradle standard structure. In my case, we don't follow src/main/java but have src/java thus, in the global file, I have dont_change_me as the value for sourceSets main java and I'm setting it to src/java in the Project's build.gradle. dont_change_me is required here as I'm/was using sourceSet.main.xx.xxx values in few of the tasks here.
sourceSets {
main {
java {
srcDir 'dont_change_me'
}
resources {
srcDir 'dont_change_me'
}
}
test {
java {
srcDir 'dont_change_me'
}
resources {
srcDir 'dont_change_me'
}
}
integrationTest {
java {
srcDir 'dont_change_me'
}
resources {
srcDir 'dont_change_me'
}
}
acceptanceTest {
java {
srcDir 'dont_change_me'
}
resources {
srcDir 'dont_change_me'
}
}
}
def sonarServerUrl = "kobalori.company.com"
sonarRunner {
sonarProperties {
property "sonar.host.url", "http://$sonarServerUrl:9000"
property "sonar.jdbc.url", "jdbc:h2:tcp://$sonarServerUrl:9092/sonar"
property "sonar.jdbc.driverClassName", "org.h2.Driver"
property "sonar.jdbc.username", "sonar"
property "sonar.jdbc.password", "sonar"
property "sonar.junit.reportsPath", "build/test-results/UT"
property "sonar.surefire.reportsPath", "build/test-results/UT"
//property "sonar.dynamicAnalysis", "reuseReports"
property "sonar.binaries", "build/classes/main"
property "sonar.java.binaries", "build/classes/main"
// property "sonar.libraries", "build/libs/*.jar"
property "sonar.sources", "src/java"
//property "sonar.sources", "src/main/groovy"
//property "sonar.sources", "src/java, src/main/groovy"
//property "sonar.tests", "test/java, src/test/groovy, src/groovy-test, src/java-test"
//property "sonar.tests", "src/test/groovy"
property "sonar.tests", "test/java, src/java-test"
//properties ["sonar.sources"] = sourceSets.main.allSource.srcDirs
//properties ["sonar.tests"] += sourceSets.test.allJava.srcDirs
//properties ["sonar.tests"] += sourceSets.integrationTest.allJava.srcDirs
}
}
//sonarRunner {
// toolVersion = '2.4'
//}
checkstyle {
configFile = new File(rootDir, "config/checkstyle.xml")
ignoreFailures = true
//sourceSets = [sourceSets.main, sourceSets.test, sourceSets.integrationTest]
sourceSets = [sourceSets.main]
}
findbugs {
ignoreFailures = true
sourceSets = [sourceSets.main]
//toolVersion = "2.0.3"
}
// pmd {
// ruleSets = ["basic", "braces", "design"]
// ignoreFailures = true
// }
//Required with Gradle 2.0+ -- 2.0+ -- 2.3
pmd {
ruleSets = ["java-basic", "java-braces", "java-design" ]
ignoreFailures = true
}
//Try this or later version too.
//pmd {
// toolVersion = '4.3'
//}
jacoco {
//toolVersion = "0.6.2.201302030002"
//toolVersion = "0.7.0.201403182114"
//toolVersion = "0.7.1.201404171759"
toolVersion = "0.7.2.201409121644"
reportsDir = file("$buildDir/customJacocoReportDir")
}
task testReport(type: TestReport) {
destinationDir = file("$buildDir/reports/tests/allTests")
//testResultDirs = file("$buildDir/test-results/allTests")
}
test {
maxParallelForks = 5
forkEvery = 50
ignoreFailures = true
//testReportDir = file("$buildDir/reports/tests/UT")
//destinationDir = file("$buildDir/reports/tests/UT")
//testResultsDir = file("$buildDir/test-results/UT")
//testLogging.showStandardStreams = true
//onOutput { descriptor, event ->
// logger.lifecycle("Test: " + descriptor + " produced standard out/err: " + event.message )
//}
//Following Jacoco test section is required only in Jenkins instance extra common file
jacoco {
//The following vars works ONLY with 1.6 of Gradle
// destPath = file("$buildDir/jacoco/UT/jacocoUT.exec")
// classDumpPath = file("$buildDir/jacoco/UT/classpathdumps")
//Following vars works only with versions >= 1.7 version of Gradle
destinationFile = file("$buildDir/jacoco/UT/jacocoUT.exec")
// classDumpFile = file("$buildDir/jacoco/UT/classpathdumps")
}
}
task integrationTest( type: Test) {
//Always run tests
outputs.upToDateWhen { false }
ignoreFailures = true
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
//testReportDir = file("$buildDir/reports/tests/IT")
//testResultsDir = file("$buildDir/test-results/IT")
//Following Jacoco test section is required only in Jenkins instance extra common file
jacoco {
//This works with 1.6
//destPath = file("$buildDir/jacoco/IT/jacocoIT.exec")
// classDumpPath = file("$buildDir/jacoco/IT/classpathdumps")
//Following works only with versions >= 1.7 version of Gradle
destinationFile = file("$buildDir/jacoco/IT/jacocoIT.exec")
// classDumpFile = file("$buildDir/jacoco/IT/classpathdumps")
}
}
task acceptanceTest ( type: Test) {
//Always run tests
outputs.upToDateWhen { false }
ignoreFailures = true
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
//testReportDir = file("$buildDir/reports/tests/AT")
//testResultsDir = file("$buildDir/test-results/AT")
//Following Jacoco test section is required only in Jenkins instance extra common file
jacoco {
//This works with 1.6
//destPath = file("$buildDir/jacoco/AT/jacocoAT.exec")
// classDumpPath = file("$buildDir/jacoco/AT/classpathdumps")
//Following works only with versions >= 1.7 version of Gradle
destinationFile = file("$buildDir/jacoco/AT/jacocoAT.exec")
// classDumpFile = file("$buildDir/jacoco/AT/classpathdumps")
}
}
jacocoTestReport {
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
//ignoreFailures = true
//executionData = files('build/jacoco/UT/jacocoUT.exec')
//executionData = files('build/jacoco/IT/jacocoIT.exec')
//executionData = files('build/jacoco/UT/jacocoUT.exec', 'build/jacoco/IT/jacocoIT.exec')
//executionData = files(['build/jacoco/UT/jacocoUT.exec', 'build/jacoco/IT/jacocoIT.exec'])
executionData = fileTree(dir: 'build/jacoco', include: '**/*.exec')
reports {
xml{
enabled true
//Following value is a file
destination "${buildDir}/reports/jacoco/xml/jacoco.xml"
}
csv.enabled false
html {
enabled true
//Following value is a folder
destination "${buildDir}/reports/jacoco/html"
}
}
//sourceDirectories = files(sourceSets.main.allJava.srcDirs)
sourceDirectories = files(['src/java','src/main/java', 'src/main/groovy'])
classDirectories = files('build/classes/main')
//------------------------------------------
//additionalSourceDirs = files(['test/java','test/groovy','src/java-test', 'src/groovy-test'])
//additionalSourceDirs = files(['src/test/groovy'])
//additionalSourceDirs += files('src/java-test')
//additionalClassDirs = files('build/classes/test')
//additionalClassDirs += files('build/classes/integrationTest')
//additionalClassDirs += files('build/classes/acceptanceTest')
//------------------------------------------
//IGNORE THE FOLLOWING
//------------------------------------------
//sourceDirectories = files(sourceSets.main.allJava.srcDirs)
//classDirectories = files(sourceSets.main.output.classesDir)
//classDirectories = files("build/classes/main")
//additionalSourceDirs = files("test/java")
//additionalSourceDirs += files("src/java-test")
//additionalClassDirs = files("build/classes/test")
//additionalClassDirs += files("build/classes/integrationTest")
//additionalSourceDirs = fileTree(dir: "test", include: "**/*.*")
//additionalSourceDirs += fileTree(dir: "src/java-test", include: "**/*.*")
//additionalClassDirs = fileTree(dir: "build/*est", include: "**/*.class")
//additionalClassDirs += fileTree(dir: "build/jacoco/*T/classpathdumps/com/thc", include: "**/*.class")
//additionalClassDirectories = fileTree(dir: "build/*est", include: "**/*.class")
//additionalClassDirectories += fileTree(dir: "build/jacoco/*T/classpathdumps/com/thc", include: "**/*.class")
//additionalSourceDirs = files(['test/java', 'src/java-test'])
//additionalSourceDirs = files(sourceSets.test.allJava.srcDirs)
//additionalSourceDirs += files(sourceSets.integrationTest.allJava.srcDirs)
//additionalSourceDirs += files(sourceSets.acceptanceTest.allJava.srcDirs)
// additionalClassDirs = files(['build/jacoco/UT/classpathdumps/com/thc', 'build/jacoco/IT/classpathdumps/com/thc'])
//additionalClassDirs = files(['build/jacoco/UT/classpathdumps/com/thc'])
//additionalSourceDirs = files('test/java', 'src/java-test')
// additionalClassDirs = files('build/jacoco/UT/classpathdumps/com/thc', 'build/jacoco/IT/classpathdumps/com/thc')
//sourceDirectories = files('src/main/java')
// classDirectories = files('build/classes/main')
//sourceDirectories = fileTree('src/main/java')
// classDirectories = fileTree('build/classes/main')
//additionalSourceDirectories = fileTree('test/java', 'test/resources', 'src/java-test')
// additionalClassDirectories = fileTree('build/classes/test', 'build/classes/integrationTest')
//additionalSourceDirs = files(sourceSets.test.allJava.srcDirs,sourceSets.integrationTest.allJava.srcDirs)
//additionalSourceDirs = files(sourceSets.*.allJava.srcDirs)
//additionalSourceDirs += files(sourceSets.test.allJava.srcDirs)
//additionalSourceDirs += files(sourceSets.integrationTest.allJava.srcDirs)
//additionalSourceDirs = files('src/java', 'test/java', 'test/resources', 'src/java-test', 'conf')
//additionalClasseDirs = files('build/classes')
//executionData = files('build/jacoco/test.exec', 'build/jacoco/integrationTest.exec', 'build/jacoco/acceptanceTest.exec')
//additionalSourceDirs = files(sourceSets.integrationTest.allSource.srcDirs)
//additionalSourceDirs = files('src/java', 'test/java', 'test/resources', 'src/java-test', 'conf')
//additionalSourceDirs = files(sourceSets.test.allJava.srcDirs)
//additionalSourceDirs = files(sourceSets.integrationTest.allJava.srcDirs)
//additionalSourceDirs = files([sourceSets.main.allJava.srcDirs)
}
}
You can ignore the // commented out lines as I was just playing around. Once your Gradle build is complete, you need to run jacocoTestReport task.
I run this:
gradle clean build jacocoTestReport
(This will get me a build, code coverage of source main code via Unit tests).
For getting, IT (Integration test code coverage or any non Unit tests coverage), I first run a external JVM (Tomcat etc). Then, I pass jacoco agent info to the external JVM (i.e. Tomcat in my case) like this (where I'm putting jacocoagent.jar inside some folder (tomcat in my case), and telling external JVM (Tomcat instance) to start populating Jacoco code coverage, this will create jacocoIT.exec file for code coverage of main source code via IT tests instead of Unit tests). NOTE: I have this PROJ_EXTRA_JVM_OPTS variable embedded in Tomcat startup script where I'm passing it to the Tomcat start command so that Tomcat instance know where to create jacocoIT.exec file:
export PROJ_EXTRA_JVM_OPTS=-javaagent:tomcat/jacocoagent.jar=destfile=build/jacoco/IT/jacocoIT.exec,append=false
Then I run Gradle task to run IT tests,
gradle integrationTest
Then, once they run successfully, you'll notice jacocoIT.exec has some file size (but it's still not complete). For Tomcat to flush the code coverage info into jacocoIT.exec file, you have to now STOP tomcat (target JVM) instance.
I run stop tomcat script and Tomcat is now stopped. At this point, I now find that my jacocoIT.exec file is now fully populated with more file size (than it what it had before Stop tomcat).
At this point, I run Gradle jacocoTestReport and SonarRunner task by running (which generates a COMBINED Unit + IT code coverage of main source code via both Unit+IT tests + also sends the info to Sonar by using/setting the -Dsonar.xx.yy=value (which you can easily pass at command line OR in Jenkins (Invoke Gradle Plugin > Switches/options box):
gradle jacocoTestReport -x test -x testClasses sonarRunner
NOTE: Make sure you pass -Dsonar.xx variable correctly.
For ex: I pass the following options/switches while calling sonarRunner task (this assumes in SonarQube instance, you have the project dashboard with required Widgets in place/enabled):
Here variable ${testType} has value=IT in it. All other variables are defined in Jenkins Global configuration (JENKINS_URL etc or they are available as Jenkins default environment variables). I'm using SVN (as source control tool) thus, SVN_URL is used (which is Jenkins default env variable if your Jenkins job is using SVN as Source control to checkout source code).
--stacktrace -x test -x testClasses -Dsonar.jacoco.itReportPath=build/jacoco/${testType}/jacoco${testType}.exec -Dsonar.sources=src/java -Dsonar.java.binaries=build/classes/main -Dsonar.binaries="build/classes/main" -Dsonar.tests=test/java,src/java-test -Dsonar.jacoco.reportPath=build/jacoco/UT/jacocoUT.exec -Dsonar.junit.reportsPath=build/test-results -Dsonar.surefire.reportsPath=build/test-results -Dsonar.dynamicAnalysis=reuseReports -Dsonar.build-stability.url=jenkins:${JENKINS_URL}/job/${JOB_NAME} -Dsonar.scm.url=scm:svn:${SVN_URL}
Related
I have been trying to run spotbugs plugin on my projects using a global build.gradle setup. The plugin is added and seems that build is running. Build and spotbugsMain both are successful when I run them using
./gradlew :com.myproject.something:build --stacktrace
./gradlew :com.myproject.something:spotbugsMain --stracktrace
But if I understand it correctly, it should generate a report (in spotbugs folder?) under build-gradle folder.
I do not see anything generated. spotbugs folder itself is not showing up.
Here is my build.gradle. Can someone please tell me what I am doing wrong? I am not sure I understand concepts of gradle completely but I have tried to use other references.
Minimal working SpotBugs setup for Android Studio
plugins {
id "com.github.spotbugs" version "4.7.2" apply false
}
group = 'com.myproject'
subprojects {
apply plugin: 'java-library'
apply plugin: 'maven-publish'
apply plugin: 'com.github.spotbugs'
buildDir = 'build-gradle'
spotbugs {
toolVersion = '4.3.0'
ignoreFailures = false
showStackTraces = true
showProgress = true
effort = 'max'
reportLevel = 'high'
maxHeapSize = '1g'
reportsDir = file("$buildDir/spotbugs")
}
tasks.withType(com.github.spotbugs.snom.SpotBugsTask) {
group 'Verification'
description 'Run Spotbugs on this project.'
dependsOn 'assemble'
reports {
xml.enabled = false
html.enabled = true
}
classDirs = files('$buildDir.absolutePath/build-gradle/classes/java/main')
sourceDirs = files('$buildDir.absolutePath/src/main/java')
}
repositories {
// the order here is important. Repositories are queried in the exact order specified here
mavenLocal()
mavenCentral()
maven {
url = uri('http://build.myproject.com:8081/nexus/content/repositories/snapshots')
allowInsecureProtocol = true
}
maven {
url = uri('http://build.myproject.com:8081/nexus/content/repositories/releases')
allowInsecureProtocol = true
}
maven {
url = uri('http://build.myproject.com:8081/nexus/content/repositories/myproject')
allowInsecureProtocol = true
}
maven {
url = uri('http://build.myproject.com:8081/nexus/content/repositories/thirdparty')
allowInsecureProtocol = true
}
}
publishing {
publications {
maven(MavenPublication) {
from(components.java)
}
}
}
test {
filter {
excludeTestsMatching "*IT"
environment 'RESOURCES_PATH', 'build-gradle/resources/test'
}
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
}
UPDATE : 07/26/2021
I tried to run full build including all the subprojects instead of individual subproject as mentioned above. I used command
./gradlew clean build --stacktrace
This time, it did not work! The full build is throwing an error as below.
Task :com.vmturbo.mediation.applicationserver.jboss:compileJava FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':com.myproject.something:compileJava'.
Could not resolve all files for configuration ':com.myproject.something:compileClasspath'.
Could not find com.github.spotbugs:spotbugs-annotations:4.7.2.
Searched in the following locations:
- file:/Users/myuser/.m2/repository/com/github/spotbugs/spotbugs-annotations/4.7.2/spotbugs-annotations-4.7.2.pom
- https://repo.maven.apache.org/maven2/com/github/spotbugs/spotbugs-annotations/4.7.2/spotbugs-annotations-4.7.2.pom
- http://build.myproject.com:8081/nexus/content/repositories/snapshots/com/github/spotbugs/spotbugs-annotations/4.7.2/spotbugs-annotations-4.7.2.pom
- http://build.myproject.com:8081/nexus/content/repositories/releases/com/github/spotbugs/spotbugs-annotations/4.7.2/spotbugs-annotations-4.7.2.pom
- http://build.myproject.com:8081/nexus/content/repositories/myproject/com/github/spotbugs/spotbugs-annotations/4.7.2/spotbugs-annotations-4.7.2.pom
- http://build.myproject.com:8081/nexus/content/repositories/thirdparty/com/github/spotbugs/spotbugs-annotations/4.7.2/spotbugs-annotations-4.7.2.pom
Required by:
project :com.myproject.something
Any idea about the problem? It seems full build does not work with above error and if I try to build only 1 subproject com.myproject.something then it runs fine but does not generate anything related to spotbugs.
I found the problem. I am not entirely sure why though. This thread helped.
https://github.com/spotbugs/spotbugs/issues/1027
In my build.gradle I was using this block ->
tasks.withType(com.github.spotbugs.snom.SpotBugsTask) {
group 'Verification'
description 'Run Spotbugs on this project.'
dependsOn 'assemble'
reports {
xml.enabled = false
html.enabled = true
}
classDirs = files('$buildDir.absolutePath/build-gradle/classes/java/main')
sourceDirs = files('$buildDir.absolutePath/src/main/java')
}
But instead when I changed that to this, all seemed to work and spotbugs folder and under it, report got generated. Apparently, I did not need to provide class and source folders at all.
spotbugsMain {
reports {
xml.enabled = false
html.enabled = true
}
}
spotbugsTest {
reports {
xml.enabled = false
html.enabled = true
}
}
FINAL build.gradle file
plugins {
id "com.github.spotbugs" version "4.7.2" apply false
}
group = 'com.myproject'
subprojects {
apply plugin: 'java-library'
apply plugin: 'maven-publish'
apply plugin: 'com.github.spotbugs'
buildDir = 'build-gradle'
spotbugs {
toolVersion = '4.3.0'
ignoreFailures = false
showStackTraces = true
showProgress = true
effort = 'max'
reportLevel = 'high'
maxHeapSize = '1g'
reportsDir = file("$buildDir/spotbugs")
}
spotbugsMain {
reports {
xml.enabled = false
html.enabled = true
}
}
spotbugsTest {
reports {
xml.enabled = false
html.enabled = true
}
}
repositories {
// the order here is important. Repositories are queried in the exact order specified here
mavenLocal()
mavenCentral()
maven {
url = uri('http://build.myproject.com:8081/nexus/content/repositories/snapshots')
allowInsecureProtocol = true
}
maven {
url = uri('http://build.myproject.com:8081/nexus/content/repositories/releases')
allowInsecureProtocol = true
}
maven {
url = uri('http://build.myproject.com:8081/nexus/content/repositories/myproject')
allowInsecureProtocol = true
}
maven {
url = uri('http://build.myproject.com:8081/nexus/content/repositories/thirdparty')
allowInsecureProtocol = true
}
}
publishing {
publications {
maven(MavenPublication) {
from(components.java)
}
}
}
test {
filter {
excludeTestsMatching "*IT"
environment 'RESOURCES_PATH', 'build-gradle/resources/test'
}
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
}
Ran these commands and they succeeded - meaning that I got spotbugs errors in code and build failed! which is what I was looking for!
./gradlew check and ./gradlew clean build --stacktrace
7 SpotBugs violations were found. See the report at: file:///Users/myuser/com.myproject.something/build-gradle/spotbugs/test.html
You can refer to this answer:
Minimal working SpotBugs setup for Android Studio.
Following which I let my android project run successfully and got the spotbugs check report. The report will be generated in path of {module_name}/build/spotbugsReports/main.html. The running command can be ./gradlew build or ./gradlew spotbugsMain.
In build.gradle of app module:
apply plugin: 'com.github.spotbugs' // <- Add this
spotbugs {
toolVersion = "3.1.3"
ignoreFailures = false
showProgress = true
reportsDir = file("$project.buildDir/spotbugsReports")
effort = "max"
reportLevel = "high"
}
tasks.withType(com.github.spotbugs.SpotBugsTask) {
group 'Verification'
description 'Run Spotbugs on this project.'
// You'll also need to enable the HTML report and disable XML report, to see a human-readable format.
reports {
xml.enabled = false
html.enabled = true
}
dependsOn 'assemble'
classes = files("$projectDir.absolutePath/build/intermediates/javac")
source = fileTree('src/main/java') // Only needed on gradle 4/5
}
// This block is only needed for gradle 4/5 only.
// It's for SpotBugs to create a 'spotbugsMain' gradle task.
sourceSets {
main {
java.srcDirs = []
}
}
android {
...
}
dependencies {
...
}
In build.gradle of root project:
buildscript {
repositories {
...
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:1.6.6'
}
}
allprojects {
repositories {
...
}
}
The Gradle Wrapper Version of my project is gradle-4.10.1-all.zip. Pay attention that when you'are using Gradle v4 - lastest Spotbugs version you could use only 1.6.6. Ref: https://gist.github.com/mik9/fdde79052fef7f03c4325734701a39d7
I have a Java-Gradle project that has multiple modules, meaning multiple build.gradle files and multiple test folders.
I have a main build.gralde and I succeeded to aggregate all the multi jacoco reports to one main report using the configuration below at my main build.gradle.
but now I want to exclude some of packages / classes from the aggregated modules.
How do I do that?
you can see also my tries below
apply plugin: 'jacoco'
apply plugin: 'java'
def otherProjects = [':module1', ':module2']
otherProjects.each {
// ensure other projects evaluated first so sourceSets are configured
evaluationDependsOn it
}
jacoco {
toolVersion = "0.8.4"
reportsDir = file("$buildDir/jacoco")
}
jacocoTestReport {
FileTree sourceTree = files().asFileTree
FileTree classTree = files().asFileTree
otherProjects.each {
sourceTree += project(it).sourceSets.main.allJava
classTree += project(it).sourceSets.main.output.asFileTree
}
additionalSourceDirs = sourceTree
additionalClassDirs = classTree
reports {
html.enabled true
html.destination file("${buildDir}/jacocoHtml")
}
// try 1
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: it, exclude: '/com/packege_from_module1/**')
})
}
// try 2
afterEvaluate {
additionalSourceDirs = files(additionalSourceDirs.files.collect {
sourceTree(dir: it, exclude: 'com/packege_from__module1/**')
})
}
// try 3
afterEvaluate {
additionalSourceDirs = files(additionalSourceDirs.files.collect {
classTree(dir: it, exclude: 'com/packege_from__module1/**')
})
}
}
Given
a/src/main/java/A.java
class A {
}
a/src/test/java/ATest.java
import org.junit.Test;
public class ATest {
#Test
public void a() {
}
}
b/src/main/java/B.java
class B {
}
b/src/test/java/BTest.java
import org.junit.Test;
public class BTest {
#Test
public void b() {
}
}
settings.gradle
rootProject.name = 'example'
include 'a'
include 'b'
and build.gradle
allprojects {
apply plugin: 'java'
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.8.3"
}
repositories {
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.12'
}
}
task jacocoAggregateReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
dependsOn = subprojects.test
sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs)
classDirectories = files(subprojects.sourceSets.main.output)
executionData = files(subprojects.jacocoTestReport.executionData)
}
using Gradle 4.10.3 or 5.4.1 execution of gradle jacocoAggregateReport will produce following report in directory build/reports/jacoco/jacocoAggregateReport/html/index.html
Now let's exclude class file A.class from report by changing
classDirectories = files(subprojects.sourceSets.main.output)
in build.gradle on
classDirectories = files(subprojects.sourceSets.main.output).asFileTree.matching {
exclude 'A.class'
}
and execution of gradle jacocoAggregateReport will produce
Your attempts did not worked, because report is constructed for all class files from both classDirectories and additionalClassDirs - no exclusion from classDirectories and additionalClassDirs in attempts 2 and 3, no exclusion from additionalClassDirs in attempt 1.
Does anyone know if a good test coverage tool (preferably Gradle plugin) exists for Kotlin? I've looked into JaCoCo a bit, but it doesn't seem to reliably support Kotlin.
As requested, here is an example build.gradle that uses Kotlin, and incorporates both Jacoco and Sonarqube integration, produces a jar and sources, and ties in Detekt for static analysis.
I had to manually add a couple things as my work build has jacoco applied by an in-house plugin.
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.10'
id 'org.jetbrains.kotlin.plugin.spring' version '1.2.10'
id 'org.springframework.boot' version '1.5.9.RELEASE'
id 'io.spring.dependency-management' version '1.0.4.RELEASE'
id 'io.gitlab.arturbosch.detekt' version '1.0.0.RC6'
id "org.sonarqube" version "2.6.2".
}
apply plugin: 'jacoco'
ext {
springBootVersion = '1.5.9.RELEASE'
springCloudVersion = 'Dalston.SR4'
kotlinVersion = '1.2.10'
detektVersion = '1.0.0.RC6'.
}
//======================= Project Info =============================================
group = 'group'
version = '0.14'
dependencyManagement {
imports {
mavenBom("org.springframework.boot:spring-boot-starter- parent:$springBootVersion")
mavenBom "org.springframework.cloud:spring-cloud-dependencies:$springCloudVersion"
}
}
repositories {
jcenter()
}
//======================= Dependencies =============================================
dependencies {
// Version MUST be explicitly set here or else dependent projects will not be able to build as Gradle will not know
// what version to use
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
compile 'org.springframework.boot:spring-boot-starter-web'
compile('org.springframework.ws:spring-ws-support') {
exclude(module: 'javax.mail')
}
compile 'org.springframework.boot:spring-boot-starter-actuator'
// Spring security
compile 'org.springframework.security:spring-security-web'
compile 'org.springframework.security:spring-security-config'
compile 'javax.servlet:javax.servlet-api'
compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml'
compile('org.apache.httpcomponents:httpclient')
compile 'com.nimbusds:nimbus-jose-jwt:4.23'
}
//======================= Tasks =============================================
defaultTasks 'build'
tasks.bootRepackage.enabled = false
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
jvmTarget = 1.8
freeCompilerArgs = ["-Xjsr305=strict"]
}
}
compileJava.options.encoding = 'UTF-8'
test.testLogging.exceptionFormat = 'full'
// ********************************
ext.coverageExclusions = [
// Configuration
'com.bns.pm.config.*',
// data classes
'com.bns.pm.domain.*',
// Account Service domain objects
'com.bns.pm.account.domain.*',
// Other items
'com.bns.pm.exceptions.DataPowerFaultException.Companion',
'com.bns.pm.controllers.ServiceExceptionHandler*',
'com.bns.pm.service.callback.DPWebServiceMessageCallback',
'com.bns.pm.service.HealthCheckService',
'com.bns.pm.util.SystemPropertiesUtilKt',
]
check.dependsOn jacocoTestCoverageVerification
jacocoTestCoverageVerification {
violationRules {
rule {
element = 'CLASS'
// White list
excludes = coverageExclusions
limit {
minimum = 0.70
}
}
}
}
jacocoTestReport {
description 'Generates Code coverage report. Fails build if it does not meet minimum coverage.'
reports {
xml.enabled = true //XML required by coveralls and for the below coverage checks
html.enabled = true
csv.enabled = false
}
def reportExclusions = coverageExclusions.collect {
it.replaceAll('\\.', '/') + (it.endsWith('*') ? '' : '*')
}
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: it, excludes: reportExclusions)
})
}
}
test.finalizedBy jacocoTestReport
afterEvaluate {
sonarqube {
properties {
property 'sonar.jacoco.reportPath', "${buildDir}/jacoco/test.exec"
property "detekt.sonar.kotlin.config.path", "detekt.yml"
property 'sonar.java.binaries', "$projectDir/build/classes/kotlin"
property 'sonar.coverage.exclusions', coverageExclusions.collect {
'**/' + it.replaceAll('\\.', '/') + (it.endsWith('*') ? '' : '*')
}
}
}
}
// Ensure source code is published to Artifactory
// Have to redefine publishing with new name as Accelerator Plugin already defined mavenJava
task sourceJar(type: Jar) {
from sourceSets.main.allSource
classifier 'sources'
}
publishing {
publications {
mavenJava2(MavenPublication) {
from components.java
artifact(sourceJar) {
classifier = 'sources'
}
}
}
}
artifactory {
contextUrl = "${artifactory_contextUrl}"
publish {
repository {
repoKey = "${artifactory_projectRepoKey}"
username = "${artifactory_user}"
password = "${artifactory_password}"
maven = true
}
defaults {
publications('mavenJava2')
}
}
}
artifactoryPublish {
dependsOn jar
}
detekt {
version = detektVersion
profile("main") {
input = "$projectDir/src"
config = "$projectDir/detekt.yml"
filters = ".*/resources/.*,.*/tmp/.*"
output = "$project.buildDir/reports/detekt"
}
}
check.dependsOn detektCheck
Good news: there is a new kotlinx-kover Gradle plugin, compatible with JaCoCo and IntelliJ.
plugins {
id("org.jetbrains.kotlinx.kover") version "0.5.0"
}
Once applied, the plugin can be used out of the box without additional configuration.
Watch its YouTube announcement video and also track its roadmap from this youtrack issue.
As said in the video, it solves the problem with inline functions and more.
Below is my gradle script and I am trying to use checkstyle plugin but I am getting some issue while using it.
apply plugin: 'java'
apply plugin: 'jacoco'
apply plugin: 'findbugs'
apply plugin: 'pmd'
apply plugin: 'checkstyle'
//-- set the group for publishing
group = 'com.rohit.singh'
/**
* Initializing GAVC settings
*/
def buildProperties = new Properties()
file("version.properties").withInputStream {
stream -> buildProperties.load(stream)
}
//add the jenkins build version to the version
def env = System.getenv()
if (env["BUILD_NUMBER"]) buildProperties.engineBuildVersion += "_${env["BUILD_NUMBER"]}"
version = buildProperties.engineBuildVersion
println "${version}"
//name is set in the settings.gradle file
group = "com.xxxx.engine"
version = buildProperties.engineBuildVersion
println "Building ${project.group}:${project.name}:${project.version}"
sourceCompatibility = 1.6
jar {
manifest {
attributes 'Implementation-Title': "${project.name}",
'Implementation-Version': "${project.version}",
'Implementation-Vendor-Id': "${project.group}"
}
}
repositories {
maven {
url "http://xjhxxxx.xxxx.xxxxx.com:99999/artifactory/repo1-cache"
}
}
dependencies {
compile ([
"com.eaio.uuid:uuid:3.2",
"org.springframework:spring-context:2.5.6",
"org.springframework:spring-beans:1.2.6" ,
"org.springframework:spring-core:1.2.3",
"org.springframework:spring-aop:3.0.6.RELEASE",
"org.springframework:spring-expression:3.0.7.RELEASE",
"org.projectlombok:lombok:1.12.2",
"com.fasterxml.jackson.core:jackson-core:2.1.3",
"com.fasterxml.jackson.core:jackson-annotations:2.2.3",
"com.fasterxml.jackson.core:jackson-databind:2.2.3",
"org.slf4j:slf4j-api:1.7.6",
"org.apache.commons:commons-lang3:3.0",
"junit:junit:4.+"
])
}
jacoco {
toolVersion = "0.7.1.201405082137"
}
test {
jacoco {
append = false
destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
classDumpFile = file("$buildDir/jacoco/classpathdumps")
}
}
jacocoTestReport {
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
executionData = fileTree(dir: 'build/jacoco', include: '**/*.exec')
reports {
xml{
enabled true
//Following value is a file
destination "${buildDir}/reports/jacoco/xml/jacoco.xml"
}
csv.enabled false
html{
enabled true
//Following value is a folder
destination "${buildDir}/reports/jacoco/html"
}
}
}
findbugs {
ignoreFailures = true
//sourceSets = [sourceSets.main]
}
pmd {
ruleSets = ["java-basic", "java-braces", "java-design"]
ignoreFailures = true
//sourceSets = [sourceSets.main]
}
checkstyle {
configFile = new File(rootDir, "config/checkstyle/checkstyle.xml")
ignoreFailures = true
sourceSets = [sourceSets.main]
}
// adding test report to taskGraph
build.dependsOn checkstyleReport
// ------ Publish the jar file to artifactory ------
artifacts {
archives jar
}
Output:
Unable to create a Checker: unable to find C:\MERCURIAL_WORKSPACE\Common\confi g\checkstyle\checkstyle.xml
Probably you don't have the checkstyle.xml in the location you are referring to. Create a simple config file like following in $projectRoot/config/checkstyle/checkstyle.xml and then try building.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker">
<module name="FileTabCharacter"/>
<module name="TreeWalker">
<module name="UnusedImports"/>
</module>
</module>
Add more modules/rulesets later on.
I'm playing with the tomcat plugin for gradle and in my build/tmp/tomcatRun/work/Tomcat/localhost/myWebApp directory its empty. Is there a way for me to specify the location of my war to deploy?
I tried
[tomcatRun, tomcatRunWar]*.destinationDir= new File("$buildDir/libs").getAbsoluteFile().getPath()
and
[tomcatRun, tomcatRunWar]*.warDirectory= new File("$buildDir/libs").getAbsoluteFile().getPath()
Update
I've added the build scripts below. When I run my new tasks I've been running
gradle build integrationTest
Here is a snippet from the parent build.gradle:
buildscript {
repositories {
add(new org.apache.ivy.plugins.resolver.URLResolver()) {
name = 'GitHub'
addArtifactPattern 'http://cloud.github.com/downloads/[organisation]/[module]/[module]-[revision].[ext]'
}
}
dependencies {
classpath 'bmuschko:gradle-tomcat-plugin:0.9.2'
}
}
allprojects {
apply plugin: "java"
apply plugin: "eclipse"
apply plugin: "idea"
ext.springVersion = "3.1.1.RELEASE"
ext.hibernateVersion = "3.6.7.Final"
ext.mysqlVersion = "5.1.20"
ext.tomcatVersion = "7.0.26"
ext.junitVersion = "4.10"
ext.httpClientVersion = "4.2"
ext.pdfboxVersion = "1.7.1"
ext.resxWebserviceVersion = "10.4.2"
loadConfiguration()
}
and my webapps build.gradle:
apply plugin: "maven"
apply plugin: "war"
apply plugin: "tomcat"
def now = new Date()
def cssDir = new File("truexpense-web/src/main/webapp/css").getAbsoluteFile().getPath()
def minCssName = 'all-min.css'
def jsDir = new File("truexpense-web/src/main/webapp/js").getAbsoluteFile().getPath()
def minJsName = 'all-min.js'
ext.requestor = ''
ext.fromAddress = ''
ext.replyAddress = ''
ext.formattedDate = now.format('dd MMM yyy HH:mm')
ext.product = 'Truexpense'
configurations {
deployerJars
jasper
mail
}
dependencies {
//Compile time but not included dependencies
providedCompile "javax.servlet:javax.servlet-api:3.0.1"
providedCompile "org.apache.tomcat:tomcat-jdbc:$tomcatVersion"
//Compile time dependencies
compile project(":truexpense-domain")
compile project(":truexpense-repository")
compile project(":truexpense-service")
compile "org.springframework:spring-core:$springVersion"
compile "org.springframework:spring-web:$springVersion"
compile "org.hibernate:hibernate-core:$hibernateVersion"
compile "org.hibernate:hibernate-envers:$hibernateVersion"
compile "org.hibernate:hibernate-ehcache:$hibernateVersion"
compile "org.hibernate:hibernate-validator:4.2.0.Final"
compile "commons-io:commons-io:2.3"
compile "commons-codec:commons-codec:1.6"
compile "org.springframework.security:spring-security-core:3.1.0.RELEASE"
compile "org.springframework.security:spring-security-config:3.1.0.RELEASE"
compile "org.springframework.security:spring-security-web:3.1.0.RELEASE"
compile "javax.mail:mail:1.4"
compile "mysql:mysql-connector-java:$mysqlVersion"
compile "com.google.visualization:visualization-datasource:1.0.2"
compile "org.ostermiller:utils:1.07.00"
compile "net.sf.ofx4j:ofx4j:1.4"
compile "org.jpedal:jbig2:1"
compile "org.apache.pdfbox:txp-fontbox:$pdfboxVersion"
compile "org.apache.pdfbox:txp-jempbox:$pdfboxVersion"
compile "org.apache.pdfbox:txp-pdfbox:$pdfboxVersion"
compile "taglibs:taglibs-unstandard:1"
compile "org.codehaus.jackson:jackson-mapper-asl:1.9.7"
compile "org.apache.httpcomponents:httpclient:$httpClientVersion"
//Runtime only dependencies
runtime "commons-beanutils:commons-beanutils-core:1.8.3"
runtime "joda-time:joda-time:2.1"
runtime "org.springframework.security:spring-security-taglibs:3.1.0.RELEASE"
runtime "org.springframework:spring-beans:$springVersion"
runtime "org.springframework:spring-context:$springVersion"
runtime "org.springframework:spring-core:$springVersion"
runtime "org.springframework:spring-expression:$springVersion"
runtime "org.springframework:spring-instrument:$springVersion"
runtime "org.springframework:spring-instrument-tomcat:$springVersion"
runtime "org.springframework:spring-jdbc:$springVersion"
runtime "org.springframework:spring-jms:$springVersion"
runtime "org.springframework:spring-orm:$springVersion"
runtime "org.springframework:spring-oxm:$springVersion"
runtime "org.springframework:spring-tx:$springVersion"
runtime "org.springframework:spring-web:$springVersion"
runtime "org.springframework:spring-webmvc:$springVersion"
runtime ("commons-fileupload:commons-fileupload:1.2.2") {
exclude group: "javax.servlet", module: "javax.servlet-api"
exclude group: "portlet-api"
}
runtime ("javax.servlet:jstl:1.2") {
exclude group: "javax.servlet", module: "javax.servlet-api"
exclude group: "javax.servlet", module: "jsp-api"
}
//Test only dependencies
tomcat "org.apache.tomcat:tomcat-dbcp:${tomcatVersion}"
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
"org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
}
//Deployments
deployerJars "org.apache.maven.wagon:wagon-http:1.0-beta-2"
[tomcatRun, tomcatRunWar]*.httpPort = 8090
[tomcatRun, tomcatStop]*.stopPort = 8081
[tomcatRun, tomcatStop]*.stopKey = 'stopKey'
task integrationTest(type: Test) {
include '**/*IntegrationTest.*'
doFirst {
tomcatRun.daemon = true
tomcatRun.execute()
}
doLast {
tomcatStop.execute()
}
}
test {
exclude '**/*IntegrationTest.*'
}
}
war {
baseName='truexpense'
eachFile {
if (it.name == 'login_css_include.jsp') {
it.expand(loginCSS: "login-min.css?t=${now.getTime()}")
}
else if (it.name == 'all_css_include.jsp') {
it.expand(allCSS: "all-min.css?t=${now.getTime()}")
}
else if (it.name == 'all_js_include.jsp') {
it.expand(allJS: "all-min.js?t=${now.getTime()}")
}
}
}
task deploy << { deploy() }
task minifyCSS << {
def files = fileTree(dir: "${cssDir}", includes: [
"analysis.css",
"header.css",
"footer.css",
"blocks.css",
"chosen.css",
"grids.css",
"space.css",
"dataTables.css",
"newCore.css",
"core.css",
"skin_clean.css",
"plugins.css",
"css3.css",
"jquery-ui.css",
"jquery.lightbox-0.5.css",
"jqueryFileTree.css",
"jquery.qtip.css",
"expense.css",
"report.css",
"zentab.css"
]).getFiles().sort({it.name})
concatenate("${cssDir}/all.css", files)
yuiCompressor("${cssDir}/all.css", "${cssDir}/${minCssName}")
yuiCompressor("${cssDir}/login.css", "${cssDir}/login-min.css")
}
task minifyJS << {
def files = fileTree(dir: "${jsDir}", excludes:[
'all*.js',
'jqtouch*.js'
]).getFiles().sort({it.name})
concatenate("${jsDir}/all.js", files)
yuiCompressor("${jsDir}/all.js", "${jsDir}/${minJsName}")
}
def yuiCompressor(from, to) {
ant.java(jar:"tools/yuicompressor-2.4.7.jar", fork: true, failonerror: true) {
arg(value: from)
arg(value: "-o")
arg(value: to)
}
}
def concatenate(filePath, files) {
File file = new File(filePath)
if (file.exists()) {
file.write("")
}
files.each { File f ->
file.append(f.getText() + '\n')
}
}
def deploy() {
println "Deleting ${tomcatHome}/webapps/${war.baseName}"
delete "${tomcatHome}/webapps/${war.baseName}"
println "Deleting ${tomcatHome}/work/Catalina/localhost/${war.baseName}"
delete "${tomcatHome}/work/Catalina/localhost/${war.baseName}"
println "Copying ${war.archiveName} to ${tomcatHome}/webapps"
copy {
from war.archivePath
into "${tomcatHome}/webapps"
}
}
How do you reference your applicationContext.xml in your web.xml? If you use the full path (/WEB-INF/classes/applicationContext.xml) then I'd probably change it to search for it on the classpath:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>