I'm trying to have Jenkins run pitest on my project.
The fact that there is a parent build.gradle with sub-projects seems to be an issue.
When running gradle pitest I get:
12:14:17 PIT >> INFO : Sending 0 test classes to minion
12:14:17 PIT >> INFO : Sent tests to minion
12:14:17 PIT >> SEVERE : Error generating coverage. Please check that your classpath contains JUnit 4.6 or above.
Exception in thread "main" org.pitest.util.PitError: Coverage generation minion exited abnormally. Please check the classpath.
I tried configuring pitest only for the subprojects, as suggented in some posts, but doesn't make any difference
subprojects { subproject ->
pitest {
verbose = true
targetClasses = ['com.xyz.*']
threads = 16
enableDefaultIncrementalAnalysis = true
historyInputLocation = ['build/reports/pitest/fastermutationtesting']
historyOutputLocation = ['build/reports/pitest/fastermutationtestingoutput']
outputFormats = ['XML', 'HTML']
timestampedReports = true
mutationThreshold = 80
}
If I try to run pitest on the subprojects, e.g. gradle subOne:pitest gradle says that such task does not exist.
Any suggestion?
The issue was actually the way the plugin was applied.
After setting
id 'info.solidsoft.pitest' version '1.3.0' apply false
in plugins and then adding
apply plugin: 'info.solidsoft.pitest'
in subprojects it all works fine.
try gradle :subOne:pitest.
You can include pitest in the main project and not needed to repeat for subprojects
Related
I tried to run a task from build.gradle using the following command:
gradle footype
However the build failed and displayed these two error messages that I want to fix:
> Configure project :
The Task.leftShift(Closure) method has been deprecated and is scheduled to
be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
And this message as well:
* What went wrong:
An exception occurred applying plugin request [id: 'java']
> Failed to apply plugin [class
'org.gradle.language.base.plugins.LifecycleBasePlugin']
> Declaring custom 'assemble' task when using the standard Gradle
lifecycle plugins is not allowed.
Here is the code of the build.gradle file:
plugins{
id "com.gradle.build-scan" version "1.10.2"
id "org.arquillian.spacelift" version "1.0.0-alpha-17"
id "java"
}
group 'k'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
task fooType {
doLast {
def foo = "bar"
println "$foo + foo = ${foo + "foo"}"
}
}
I searched on other posts and they all seem to mention a task called clean() which doesn't appear in my code, so I'd like to know what's the problem.
Thank you muchly for reading this post.
When it comes to this message:
Configure project :
The Task.leftShift(Closure) method has been deprecated and is scheduled to
be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
it is just a warning. It states that one (possibly more) plugin you applied uses << which will be removed in version 5.0 of gradle in favour of doLast. You are not using << directly in your script and that's ok. To eliminate this warning first of all you need to know which plugin uses it, then raise an issue on plugin's site asking for deprecated code elimination.
When it comes to the second message it's an error and in single build script nothing can be done about it. Two plugins java and org.arquillian.spacelift have declared a task with the same name (it's assemble) - this is a conflict. Maybe you can split you project into a multimodule?
When I run gradle tasks it always lists dependencies task; But when I run the following code in my build.gradle it always return null : project.tasks.findByName('dependencies')
My requirement is to print the output of dependencies task into the log for reference as part of build.
I am on gradle version 1.11 (not authorized to upgrade)
Please help:
You may try to use a custom task of org.gradle.api.tasks.diagnostics.DependencyReportTask type, and configured to print just sepecified configuration dependencies, as:
task printDeps(type: org.gradle.api.tasks.diagnostics.DependencyReportTask) {
configurations = project.buildscript.configurations + project.configurations
}
If you wish, you may exclude buildscript dependencies, if you don't need them.
I have a java project on my laptop and I am building it with gradle.
All dependencies are in file system as I am off line most of the time when working on it. They are not too many anyway.
build.gradle:
repositories {
flatDir {
dirs "${rootDir}/lib/main", "${rootDir}/lib/test", "${rootDir}/lib/quality"
}
}
ext.configDir = "${rootDir}/gradle/config"
ext.scriptsDir = "${rootDir}/gradle/scripts"
Now I need to add some quality checks against my code. I was lucky to get PMD checks working but not so lucky with checkstyle. The example from gradle distribution, the gradle in action book I read, the gradle documentation does not seem to be rocket science but I just cant get it to work which become very frustrating, especially that with ant that would have been a five minutes task. Anyway this is my gradle.build entry for checkstyle:
apply from: "${scriptsDir}/checkstyle.gradle"
and this is my checkstyle.gradle (partially shown):
apply plugin: 'checkstyle'
ext.checkstyleConfigDir = new File(configDir, "checkstyle")
ext.checkstyleReportsDir = new File(reportsDir, "checkstyle")
ext.xslStyleFile = new File(checkstyleConfigDir, "checkstyle-noframes.xsl")
checkstyle {
toolVersion = '6.10.1'
configFile = new File(checkstyleConfigDir, 'sun_checks.xml')
ignoreFailures = true
showViolations = true
}
checkstyleMain.doLast {
def main = new File(checkstyleReportsDir, "main.xml")
if (main.exists()) {
ant.xslt(in: main, style: xslStyleFile, out: new File(checkstyleReportsDir, "main.html"))
}
}
dependencies {
checkstyle( 'com.puppycrawl.tools:checkstyle:6.10.1' )
}
However when running my build the checkstyle task fails like below:
* What went wrong:
Execution failed for task ':checkstyleMain'.
> java.lang.ClassNotFoundException: com.puppycrawl.tools.checkstyle.CheckStyleTask
Looking inside the checkstyle-6.10.1.jar I can see there is not such a class as com.puppycrawl.tools.checkstyle.CheckStyleTask but there is one called com.puppycrawl.tools.checkstyle.ant.CheckStyleAntTask instead and I suspect this is the one that gradle should invoke. However I have no idea about how to make gradle invoke that.
The only one suspition I have is that my toolVersion = '6.10.1' is not properly defined and gradle invokes using some default. However all gradle api documentation says about that is this: "String toolVersion The version of the code quality tool to be used."
So what I am doing wrong and how should I fix it.
Thank you in advance for your inputs.
You're running into a bug in Gradle (GRADLE-3314). This issue is fixed in Gradle 2.7 which should be out soon. Would you mind verifying that the issue is resolved with the latest 2.7 release candiate?
You can grab Gradle 2.7-rc-2 from the gradle release candidate landing page.
I'm trying to get jacoco+gradle work together. Looking at this forum it seems some people have successfully done that. But when I tried I got a strange exception.
What I did:
1.Downloaded gradle 2.2.1 and configured env variables, etc.
2.Downloaded jacoco 0.7.1 from http://www.eclemma.org/jacoco/
3.added:
apply plugin: 'jacoco'
and
buildTypes {
debug
{
testCoverageEnabled true
...
in the build.gradle
4.run gradle build
5.I got an error saying the jacoco agent jar cannot be found, etc. Error message showed it tried to search files under C:\Program Files (x86)\Android\android-sdk\extras\android\m2repository... etc.
6.I manually unzipped the jacoco jar files and put them in the place where the error message mentioned and the error message disappeared.
7.Then I ran gradle build. I got the following new error when running the built-in instrumentDebug task:
Caused by: : taskdef A class needed by class org.jacoco.ant.InstrumentTask cannot be found: org/jacoco/core/runtime/IExecutionDataAccessorGenerator using the classloader AntClassLoader[C:\Program Files (x86)\Android\android-sdk\extras\android\m2repository\org\jacoco\org.jacoco.ant\0.7.1.201405082137\org.jacoco.ant-0.7.1.201405082137.jar]
at org.apache.tools.ant.taskdefs.Definer.addDefinition(Definer.java:612)
at org.apache.tools.ant.taskdefs.Definer.execute(Definer.java:237)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.gradle.api.internal.project.ant.BasicAntBuilder.nodeCompleted(BasicAntBuilder.java:77)
at org.gradle.api.internal.project.ant.BasicAntBuilder.doInvokeMethod(BasicAntBuilder.java:92)
at com.android.build.gradle.internal.coverage.JacocoInstrumentTask.instrument(JacocoInstrumentask.groovy:51)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:63)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:218)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:211)
Caused by: java.lang.ClassNotFoundException:
at org.jacoco.core.runtime.IExecutionDataAccessorGenerator
at org.apache.tools.ant.AntClassLoader.findClassInComponents(AntClassLoader.java:1366)
at org.apache.tools.ant.AntClassLoader.findClass(AntClassLoader.java:1315)
at org.apache.tools.ant.AntClassLoader.loadClass(AntClassLoader.java:1068)...
When I used process monitor (My dev machine is Win 7), I saw there was no access to org.jacoco.core-0.7.1.201405082137.jar,which the org.jacoco.ant.InstrumentTask class resides in. So I think the gradle did not pass the file path to org.apache.tools.ant.AntClassLoader correctly.
I have tried below ways but none of them worked:
Add all jacoco jar files to CLASSPATH environment variable.
Add the jacoco jar files to ant libs, gradle libs,gradle libs/plugins, folder.
Look at source code of gradle 2.2.1. Clueless at this moment...
Does anyone know how to resolve this problem?
Thanks in advance!
Edit:
The main purpose is to:
1. Let jacoco build an instrumented apk file
2. Manually test the apk file (Not auto test)
3. Let jacoco generate coverage report
Update:
I just found when executing InstrumentDebug task, the gradle starts a new process with below command:
"C:\Program Files\Java\jdk1.8.0_25\bin\java.exe" -XX:MaxPermSize=512m -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country=CN -Duser.language=zh -Duser.variant -cp D:\gradle-2.2.1\gradle-2.2.1\lib\gradle-launcher-2.2.1.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 2.2.1 D:\gradle-2.2.1\gradle-2.2.1\daemon 120000 744501ac-32c1-4930-82bd-59e0a9e2b92d -XX:MaxPermSize=512m -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country=CN -Duser.language=zh -Duser.variant
As you can see the class path is hard coded, which overwrites what defined in environment variable. So the required core lib of jacoco could not be found and thus caused this problem. I'm now trying to see where this process is started and whether there is a way to change the -cp option.
Update2:
I finally found this process is started by gradle-launcher-2.2.1.jar. See below code. I'm now trying to see whether it's possible to change DefaultModuleRegistry and make registry.getGradleHome() == null. In the meantime could anyone who has successfully used jacoco+gradle tell me which version of gradle are you using?
public DaemonStartupInfo startDaemon()
{
DefaultModuleRegistry registry = new DefaultModuleRegistry();
Set<File> bootstrapClasspath = new LinkedHashSet();
bootstrapClasspath.addAll(registry.getModule("gradle-launcher").getImplementationClasspath().getAsFiles());
if (registry.getGradleHome() == null)
{
bootstrapClasspath.addAll(registry.getFullClasspath());
}
if (bootstrapClasspath.isEmpty()) {
throw new IllegalStateException("Unable to construct a bootstrap classpath when starting the daemon");
}
new JvmVersionValidator().validate(this.daemonParameters);
List<String> daemonArgs = new ArrayList();
daemonArgs.add(this.daemonParameters.getEffectiveJavaExecutable());
List<String> daemonOpts = this.daemonParameters.getEffectiveJvmArgs();
LOGGER.debug("Using daemon opts: {}", daemonOpts);
daemonArgs.addAll(daemonOpts);
daemonArgs.add("-cp");
daemonArgs.add(CollectionUtils.join(File.pathSeparator, bootstrapClasspath));
daemonArgs.add(GradleDaemon.class.getName());
daemonArgs.add(GradleVersion.current().getVersion());
daemonArgs.add(this.daemonDir.getBaseDir().getAbsolutePath());
daemonArgs.add(String.valueOf(this.daemonParameters.getIdleTimeout()));
daemonArgs.add(this.daemonParameters.getUid());
...
}
See if this helps.
I'm not using Gradle 2.2.1 but this is what I have in my Global Gradle file (i.e. a file in $GRADLE_HOME/init.d level file). File name can be anything with .gradle extension.
allprojects {
apply plugin: 'java'
apply plugin: 'pmd'
apply plugin: 'findbugs'
apply plugin: 'checkstyle'
apply plugin: 'jacoco'
//NOTE1: The following soureSet section is NOT required, if your folder structure follows what Gradle says where your main source should reside, where test (Unit tests) should reside, and where other like integrationTest (integration tests code reside). If your project structure doesn't follow the Gradle defined structure, then you can define that as my source code is not under src/main/java but is under src/java. The use of "sourceSet" section in this global file is only helping to use some conventional values in this global level file for ex: see integrationTest task and jacocoTestReport task below (you can't use those values if sourceSet is NOT defined in this file and if your project doesn't following the Gradle defined structure).
//NOTE2: Here in the global level Gradle file, I'm using values for sources for main, test, integrationTest etc as "dont_change_me" as I don't know what all projects (which will use this Gradle's global level file), will have what source code structure. The main / actual values of the sources for main, test and integrationTest task MUST be defined in the PROJECT's build.gradle file in sourceSets { main { java { srcDir 'src/java' } } } way.
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'
}
}
}
//...more code here
//...more code here
// The following is necessary to get code coverage info out. Compile with debug mode.
tasks.withType(Compile) {
options.debug = true
options.compilerArgs = ["-g"]
}
jacoco {
//toolVersion = "0.6.2.201302030002"
//toolVersion = "0.7.0.201403182114"
//toolVersion = "0.7.1.201404171759"
//This is latest than above, you may find later versions in online Maven repository.
toolVersion = "0.7.2.201409121644"
//OK I don't need the following folder to be created as I'll define my own.
// reportsDir = file("$buildDir/customJacocoReportDir")
}
//The following section is for UNIT tests (as build task in Gradle calls test task for free)
test {
maxParallelForks = 5
forkEvery = 50
ignoreFailures = true
// I want my reports (html) files to be created in a user defined folder UT(Unit test in build/reports/UT folder) and xml files (in user defined folder UT folder) under build/test-results/UT folder.
testReportDir = file("$buildDir/reports/tests/UT")
testResultsDir = file("$buildDir/test-results/UT")
//Following jacoco session will RUN in GRADLE's JVM session (during build / test time). This is different JVM than what many think of a runtime/Tomcat JVM session where we run a .war/.ear/etc file of an app to run that app and if you want to get code coverage of your main source code using non-unit tests from a Tomcat JVM, then see next task (integrationTest) as the following jacoco section in this "test" task is just for UNIT tests running in Gradle JVM session on a machine.
jacoco {
//NOTE: The following vars works ONLY with Gradle <= 1.6 version
// Create jacoco .exec file for Unit test in a user defined location
destPath = file("$buildDir/jacoco/UT/jacocoUT.exec")
//The following line is not that usesful acc. to my experience so commented it.
//classDumpPath = file("$buildDir/jacoco/UT/classpathdumps")
//NOTE: 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 }
//Ignore the failures if any during tests and don't mark the Gradle task as failed.
//You can comment this line if you want your gradle task to fail as soon as it finds any failing tests.
ignoreFailures = true
//This is telling Gradle that where it'll find class files from integration tests source code
testClassesDir = sourceSets.integrationTest.output.classesDir
//What path to use in classpath for integration tests
classpath = sourceSets.integrationTest.runtimeClasspath
//My custom location where I want my html reports files and xml result times of integration tests
testReportDir = file("$buildDir/reports/tests/IT")
testResultsDir = file("$buildDir/test-results/IT")
//Jacoco section in IT tests is NOT required here. Why as it'll never generage a coverage report this way as this way of using jacoco section in integrationTest task is telling Gradle to use jacoco in Gradle JVM and for getting code coverage you have to run jacoco/jacocoagent.jar in Target JVM (which is Tomcat or similar) by introducing jacocoagent.jar and other parameters for jacoco to Tomcat using one of Tomcat's -Dxxx option (see Jacoco help on how to do this). As the following is not required, I'm commenting the following jacoco code(otherwise if used, it'll always give you 0% coverage).
//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")
//}
}
jacocoTestReport {
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
ignoreFailures = true
//Use any .exec file found before generating coverage report i.e. it'll give you combined coverage report if you have both jacocoUT.exec and jacocoIT.exec or other .exec files in build/jacoco/xx folders.
executionData = fileTree(dir: 'build/jacoco', include: '**/*.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'])
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"
}
}
//The following is an example of using Gradle conventional way of saying where is my main source code directory
//sourceDirectories = files(sourceSets.main.allJava.srcDirs)
sourceDirectories = files(['src/java', 'src/groovy'])
classDirectories = files('build/classes/main')
}
}
In Project's build.gradle, you define sourceSets section (with actual values) if your project structure if different than what Gradle says it should be. You define dependencies (i.e. for compile you need this .jar, for test or integrationTest, you need this .jar or .class from main/test etc).
Then, if you run gradle clean build, you'll get jacoco code coverage data for UT(Unit tests) under build/jacoco/UT folder in the form of an .exec file. Under build/reports/... html folder, you'll find jacoco main index.html which will show you the code coverage report.
If you want code coverage report from non-Unit tests (i.e. Integration tests etc), then attach the following parameter to the target JVM. I use Tomcat, so I'm attaching this, where testType is a variable which I use to find/tell whether I'm running IT(Integration Tests), AT (Acceptance Tests) or ST (Selenium GUI tests).
export PROJ_EXTRA_JVM_OPTS="-javaagent:tomcat/jacocoagent.jar=destfile=build/jacoco/${testType}/jacoco${testType}.exec,append=false"
and in startTomcat.sh script which I use, you'll notice I'm using the above variable and passing it to Tomcat's JVM as that's the JVM which is running my project's main .war/.ear file which has the main source code class files against which I want my code covreage data using Integration/Acceptance/other non-UNIT type tests:
## Tomcat command - JDK 1.6/Tomcat 6.0
TOMCAT_CMD="$JAVA_HOME/bin/java $TOMCAT_JVM_ARGS \
$OPTIT_JVM_ARGS \
$JPROF_JVM_ARGS \
$PROJ_EXTRA_JVM_OPTS \
org.apache.catalina.startup.Bootstrap $TOMCAT_CFG_FILE_ARGS start"
The above variable needs to be there in the Tomcat start script i.e. when Tomcat starts, it should get the above variable in its JVM session. Once this is done, you have to run "gradle integrationTest" then stop your Tomcat session(only then it'll flush the code coverage data to jacocoIT.exec file) and then if you run "gradle jacocoTestReport", it'll read the jacocoIT.exec file and genreate jacoco code coverage report for your main source code which your Integration/Acceptance/Selenium Tests tried to cover.
I am trying out the new Sonar Runner task recently released in gradle 1.5. What I would like to do is be able to make the sonar runner task dependent on another task so that I can set the Sonar properties correctly for this project (i.e. sonar.sources, sonar.binaries, sonar.libraries, sonar.java.source, sonar.java.target).
Specifically I am using an osgi build tool called bnd which will provide these values when an ant init task is executed (note that whilst I include the default bnd build.xml file, my complete build is really being done using gradle).
I thought I would be able to customize the sonar runner task by doing this (this is a multi-module build):
subprojects {
sonarRunner.dependsOn init
}
Eventually adding something like this (from what I understand of the bnd ant variables):
subprojects {
sonarRunner {
sonarProperties {
property "sonar.java.source", ant.property["project.sourcepath"]
property "sonar.java.target", ant.property["project.output"]
property "sonar.sources", ant.property["project.allsourcepath"]
property "sonar.libraries", ant.property["project.buildpath"]
}
}
sonarRunner.dependsOn init
}
Unfortunately when I try to add the dependsOn I get the error:
* What went wrong:
A problem occurred evaluating root project 'myproject'.
> Could not find property 'init' on project ':com.company.myproject.mymodule'.
If I try to make sonarRunner depend on a gradle task I get the following error:
* What went wrong:
A problem occurred evaluating root project 'myproject'.
> Could not find method dependsOn() for arguments [task ':gradletask'] on org.gradle.api.sonar.runner.SonarRunnerExtension_Decorated#c4d7c0c.
Am I missing something obvious here? If someone could point me in the right direction it would be a big help.
Your problem with not being able to call dependsOn() on sonarRunner task comes from the fact that the plugin defines both both sonarRunner extension and a sonarRunner task. It looks like extensions take precedence over tasks when objects are resolved by name in a gradle build file, hence your stacktrace points out that you are trying to call dependsOn() on an instance of org.gradle.api.sonar.runner.SonarRunnerExtension_Decorated instead of caling it on a SonarRunner task instance.
I think that if you retrieved the task from the task container explicitly you should be ok:
tasks.sonarRunner.dependsOn init
The root project gradle file is evaluated before the child project gradle files, that means init does not exist on the location you try to address it.
A workaround if you want to declare dependencies in the root project is to use afterEvaluate as described in http://www.gradle.org/docs/current/userguide/build_lifecycle.html, try:
subprojects {
afterEvaluate{
sonarRunner.dependsOn init
}
}
Another solution would be to add the dependency in the sub projects, directly or by applying another root gradle file.
apply from: '../sonardependency.gradle'
If anyone is interested, this is one way of getting the bnd information to be set correctly in Sonar for each subproject (I am sure there are better ways):
subprojects {
afterEvaluate {
sonarRunner {
sonarProperties {
ant.taskdef(resource:"aQute/bnd/ant/taskdef.properties",
classpath: "../cnf/plugins/biz.aQute.bnd/biz.aQute.bnd-2.0.0.jar");
def projectDir = project.rootDir.toString() + "/" + project.name;
ant.bndprepare(basedir:projectDir,print:"false",top:null);
def binaries = ant.properties['project.buildpath'].split(':') as ArrayList;
binaries.remove(0);
def binariesString = binaries.join(',');
properties["sonar.java.source"] = ant.properties['javac.source'];
properties["sonar.java.target"] = ant.properties['javac.target'];
properties["sonar.binaries"] = ant.properties['project.output'].replace(':',',');
properties["sonar.sources"] = ant.properties['project.sourcepath'].replace(':',',');
properties["sonar.libraries"] = binariesString;
}
}
}
}