bmuschko / gradle-clover-plugin

Gradle plugin for generating a code coverage report using Clover
Apache License 2.0
74 stars 49 forks source link

Issues using Clover plugin 2.2.2 and Gradle version 4.10.1 #132

Closed brahma712 closed 5 years ago

brahma712 commented 5 years ago

I am still having issues resolving Java classes in my project. Here is my build file for reference...

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.bmuschko:gradle-clover-plugin:2.2.2'
    }
}
plugins {
    id 'java'
    id 'groovy'
}
group 'xxxxxx'
sourceCompatibility = 1.8

allprojects {
    apply plugin:'java'
    apply plugin: 'groovy'
    apply plugin: 'com.bmuschko.clover'

    repositories {
        mavenCentral()
        jcenter()
    }
    dependencies {
        clover 'org.openclover:clover:4.3.1'
    }
}
task wrapper(type: Wrapper) {
    gradleVersion = '4.10.1'
}

dependencies {
    // https://mvnrepository.com/artifact/org.codehaus.groovy/groovy
    compile group: 'org.codehaus.groovy', name: 'groovy', version: '2.5.3'

    // https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-xml
    compile group: 'org.codehaus.groovy', name: 'groovy-xml', version: '2.5.3'

    // https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-json
    compile group: 'org.codehaus.groovy', name: 'groovy-json', version: '2.5.3'

    // https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-core
    compile group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.0'

    // https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-events
    compile group: 'com.amazonaws', name: 'aws-lambda-java-events', version: '2.2.4'

    // https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3
    compile group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.11.458'

    // https://mvnrepository.com/artifact/org.spockframework/spock-core
    testCompile group: 'org.spockframework', name: 'spock-core', version: '1.2-groovy-2.5'

    // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.0'

    // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
    testRuntime group: 'org.apache.commons', name: 'commons-lang3', version: '3.0'
}

I have a multi-module project and each module has a src/main/groovy and src/main/java. Do I need to define sourceSets in my allProjects closure? Am I missing some configuration? When I run gradlew clean cloverAggregateReports it fails to compile my java classes.

Originally posted by @brahma3691 in https://github.com/bmuschko/gradle-clover-plugin/issues/131#issuecomment-471575742

Alex-Vol-SV commented 5 years ago

There is no need to define sourceSets if you use the standard source layout. However, src/java is not standard. src/main/java is the standard.

Also, I notice one issue with your build.gradle. You only define dependencies to modules in the root project. The allprojects closure does not apply the dependencies block you have to the subprojects.

This is not a Clover plugin issue, your build is configured incorrectly even without the Clover plugin.

Remove the plugin, get your project building first without Clover. Then add the plugin after you have solved your basic Gradle issues.

brahma712 commented 5 years ago

I have a src/main/groovy and a src/main/java in all my modules. If I remove the plugin, my project builds fine.

Alex-Vol-SV commented 5 years ago

You need to provide more details. I have many multimodule projects where this plugins works just fine. I suspect you have some issue in the project dependencies as you are not giving enough details to figure out what is going on or a specific error that needs to be resolved.

I am inclined to say that your multimodule setup is incomplete because of the observation I made regarding the dependencies that you appear to provide in the root project and not in allprojects.

Alex-Vol-SV commented 5 years ago

FYI, you should change the wrapper task definition to avoid redefining the task.

wrapper {
    gradleVersion = '4.10.1'
}

That should be sufficient to configure the default wrapper task.

brahma712 commented 5 years ago

I get groovyc compile errors on my java classes. only one of my modules has java classes. Rest of them don't have any java classes so it only fails on one module.

  [groovyc] org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
  [groovyc] C:\.....r\src\main\groovy\org\.....\PlatformComposer.groovy: 36: unable to resolve class xxxxPlatform
  [groovyc]  @ line 36, column 20.
  [groovyc]                     xxxxPlatform xxxPlatform = mapper.load(xxxPlatform.class, platformIdref)
  [groovyc]                       ^
  [groovyc]
Alex-Vol-SV commented 5 years ago

The Gradle Clover plugin switches compilation to use the groovyc compiler via Ant task instead of the Gradle CompileGroovy task. This is necessary to invoke the Clover library during compilation and instrument the code. Are you making any complex sourceSet/classpath manipulations in your projects to get this to compile? Where is the definition of the xxxxPlatform class found in your code? Without the full picture I cannot say what you might be doing to trigger this.

brahma712 commented 5 years ago

All my java classes are under src/main/java.. for the module so the xxxxPlatform class lives under src/main/java too. i.e the java classes and the groovy classes that use the java classes are under the same high level src/main package. Does that help? I can try to include the plugin into a module's build file and see if it works just for that module.

Alex-Vol-SV commented 5 years ago

That is strange, this is a very common configuration with Groovy referencing Java classes. It is the case of joint Groovy/Java compilation where the Groovy compiler is doing the compilation for both Java classes and Groovy classes. It is a supported use case.

Can you try the following change? Move the java classes from src/main/java to src/main/groovy keeping their package levels the same. This might explain where the code might have the issue and help work around it.

Do not rename the .java files to .groovy, just move them. The compiler is able to tell the difference by the name.

brahma712 commented 5 years ago

That actually fixes the issue I had. However, I get a different issue now...


>gradlew clean cloverAggregateReports

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':cloverAggregateReports'.
> You must specify one or more coverage databases to merge using a nested  <cloverdb> or <cloverdbset> element.
Alex-Vol-SV commented 5 years ago

You cannot run clean and cloverAggregateReports. cloverAggregateReports should be run together with the primary build to aggregate the reports generated by the cloverGenerateReport in check subproject. Clean removed all the data the aggregate task needs to do the work.

brahma712 commented 5 years ago

I get the same error even without the clean. I ran gradlew build first. and then gradlew cloverAggregateReports. I assume that I should see reports generating under build/reports?

Alex-Vol-SV commented 5 years ago

Then your builds are not activating clover correctly. There should be reports generated for each individual subproject. Are you getting clover.db databases created in the subdirectories? In each subproject there should be a build/.clover directory that contains clover.db files. These are what cloverAggregateReports expects to find when it runs and merge their contents into an aggregate database at the root project with the collected coverage information.

brahma712 commented 5 years ago

I see a .clover folder but I do not see any clover.db databases created. I see a folder called "historypoints" but that's it.

brahma712 commented 5 years ago

Do I need

clover 'org.openclover:clover:4.3.1'

in all my subprojects build files?

Alex-Vol-SV commented 5 years ago

Your allprojects configuration already does the dependency in all your subprojects.

I am not talking about the .clover in the project directory. I am talking about the build/.clover directory in each build subproject directory.

brahma712 commented 5 years ago

build/.clover directory does not exist under the build directory in my sub modules. Not even in my root project's build file.

brahma712 commented 5 years ago

I do get a .clover directory under the build directory if I add the configuration in the build file for my submodule and run gradlew cloverGenerateReport from the submodule.

Alex-Vol-SV commented 5 years ago

Typical configuration examples for clover are in the functional tests area. Multiproject build.gradle

You should be configuring some of the clover closure parameters although in my experience the default works for most.

Does your root project have java code or is it just a container project for the subprojects?

brahma712 commented 5 years ago

Just a container for the subprojects. No code in there.

brahma712 commented 5 years ago

Even with the clover configuration, my build fails with the same error. I believe I am missing something in the build.gradle file. I compared the structure with the file you linked and I think all of that matches except I dont have a sub-projects block.

Alex-Vol-SV commented 5 years ago

The allprojects block encompasses the subprojects block. You are not configuring any options for clover in the clover closure which means you get the defaults only. Since your top level project is a container project with no code I would have a subprojects block to configure the code generating projects with appropriate settings and a top level clover configuration in the root project. Also, your root project has no use for the java or groovy plugins and even the dependencies block. There is no code therefore the dependencies are unused.

brahma712 commented 5 years ago

Sure, but that change didn't fix much.. I am not sure what I am doing wrong.. Below is my revised build.gradle file. I am wondering if this structure would make a difference:

Root Project(container for modules) has a root build.gradle file
|
| _ _ Module1 (container for more modules) This does not have a build.gradle file
       |
       | _ _ module1 has a build.gradle file
       | _ _ module2 has a build.gradle file
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.bmuschko:gradle-clover-plugin:2.2.2'
    }
}

allprojects {
    apply plugin: 'com.bmuschko.clover'
    repositories {
        jcenter()
    }
    dependencies {
        clover 'org.openclover:clover:4.3.1'
    }
}

subprojects {
    apply plugin:'java'
    apply plugin: 'groovy'
    sourceCompatibility = 1.8
}

task wrapper(type: Wrapper) {
    gradleVersion = '4.10.1'
}

I still have the same error:

gradlew cloverAggregateReports

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':cloverAggregateReports'.
> You must specify one or more coverage databases to merge using a nested  <cloverdb> or <cloverdbset> element.
Alex-Vol-SV commented 5 years ago

Add this to your allprojects block

allprojects {
    apply plugin: 'com.bmuschko.clover'
    repositories {
        jcenter()
    }
    dependencies {
        clover 'org.openclover:clover:4.3.1'
    }
    clover {
            enabled = true
            report {
                json = true
                html = true
                pdf = true
            }
    }
}

See if that makes a difference. Should not be required but might be worth a try.

brahma712 commented 5 years ago

no luck. I had tried enabling the html reporting but that didnt make a difference either.

brahma712 commented 5 years ago

Here is some weirdness: I modified the build.gradle file in one of the modules as below:

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.bmuschko:gradle-clover-plugin:2.2.2'
    }
}
plugins {
    id 'groovy'
    id 'java'
}
apply plugin: 'com.bmuschko.clover'

group 'Auditd'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}
clover {
    enabled = true
}

dependencies {
    // https://mvnrepository.com/artifact/org.codehaus.groovy/groovy
    compile group: 'org.codehaus.groovy', name: 'groovy', version: '2.5.3'

    // https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-xml
    compile group: 'org.codehaus.groovy', name: 'groovy-xml', version: '2.5.3'

    // https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-core
    compile group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.0'

    // https://mvnrepository.com/artifact/org.spockframework/spock-core
    testCompile group: 'org.spockframework', name: 'spock-core', version: '1.2-groovy-2.5'

    clover 'org.openclover:clover:4.3.1'

}

When I run gradlew cloverGenerateReport I get a build/.clover directory with nothing in it.

Alex-Vol-SV commented 5 years ago

I have never seen this and cannot help any further. As a last resort you could capture a full debug build log and attach to this issue. I can see if something is evident in the log.

gradlew --debug build > debug.log
brahma712 commented 5 years ago

debug.log

brahma712 commented 5 years ago

Is another option installing open clover manually? Does that work with multi projects?

Alex-Vol-SV commented 5 years ago

No, OpenClover does not work by itself. You need a Gradle plugin to drive it. They have a plugin alternative but it is not supporting Groovy.

I cannot see your project performing any unit test work. Does your project have any unit tests? Coverage is a function of the code being executed during unit tests. That is the meaning of coverage. Your code does not actually have unit tests!

Alex-Vol-SV commented 5 years ago

It appears you are a bit clueless when it comes to coverage. Clover measures "Unit Test Code Coverage". This means your code must be executed by unit test code written by you with the purpose of testing the code paths within your implementation and verifying correctness. The coverage metric is just a measurement that can show you where you might have missed some conditional testing that must be expanded by additional test conditions in your unit tests.

brahma712 commented 5 years ago

Yes, my project has tests. They are spock tests under src/test/groovy. They exist for all modules that have the code.

brahma712 commented 5 years ago

I have used Clover before. And I know that it measures unit test coverage. My tests run when I run gradlew build locally. I will look into it why they aren't specifically "unit" tests Thanks for your help.

brahma712 commented 5 years ago

For your information, here is what I had to do to fix things: I had to supply sourceSets for the tests configuration which is in my case src/test/groovy and src/test/java. Even though this is standard according to gradle documentation - however clover for some reason could not figure it out. Here is what I added:

 sourceSets {
        main {
            java {
                srcDirs = ['src/main/java', 'src/main/groovy']
            }
        }
        test {
            java {
                srcDirs = [ 'src/test/groovy', 'src/test/java']
            }
        }
    }

I also had to add the following dependency: testCompile 'junit:junit:4.12' Is this a requirement for the plugin? I did not see any documentation anywhere that states that.

thank you for your time on this.

Alex-Vol-SV commented 5 years ago

The issue is not with this plugin. The issue is with your project. Your projects acted as if there were no unit tests at all. At least that is what the debug log claimed. For each one of the test tasks the log claimed there were no matching sources and therefore they were skipped. In my opinion your unit tests were somehow not seen by the defaults. The most weird part is that your source sets actually match what should be the defaults.

Here is what the debug log states for each of your test tasks prior to your fix which made me assume you had no unit tests defined.

13430: 17:59:06.480 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Workflow:OptimusSCAPExporter:test'
 14016: 17:59:06.725 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:UnixLinux:Auditd:test'
 14703: 17:59:08.438 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:UnixLinux:KernelModule:test'
 15279: 17:59:08.679 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:Windows:AccessToken:test'
 15855: 17:59:08.911 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:Windows:AuditEventPolicySubcategories:test'
 16431: 17:59:09.151 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:Windows:LockoutPolicy:test'
 17007: 17:59:09.379 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:Windows:PasswordPolicy:test'
 17583: 17:59:09.608 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:Windows:RSOPSecuritySettingBoolean:test'
 18159: 17:59:09.840 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:Windows:Registry:test'
 18735: 17:59:10.076 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:Windows:RegistryUser:test'
 19311: 17:59:10.313 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:Windows:User:test'
 19895: 17:59:10.548 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:Windows:UserRightsAssignment:test'
 20471: 17:59:10.775 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:Windows:UserRightsAssignmentDeny:test'
 21066: 17:59:11.017 [DEBUG] [org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository] No discovered inputs for task ':Transforms:Windows:UserSID55:test'

I suspect that your multilevel nesting structure of this is causing the allprojects/subprojects blocks to apply partially to the subprojects. It is very likely that you did not actually configure each project as you might think causing them to fail this way.

Not having the rest of your project build files I cannot make any more assumptions.

Alex-Vol-SV commented 5 years ago

As for the junit dependency, that is a requirement of Spock. Spock is a JUnit derivative and should have that as a transitive dependency. I commonly add junit as well as Spcok in all my projects. Again, nothing relating to this plugin, just missing or incomplete project layout configuration in your multilevel project structure.

brahma712 commented 5 years ago

It is extremley weird that I need to specify those sourceSets - I agree. Another strange part is that I get report generation for one module.. but not the others.. and what you saw in the logs is probably why its not generating reports for the other modules.. This is so strange.. I cant seem to be able to tell how the structure of the gradle build does not make sense.

Alex-Vol-SV commented 5 years ago

Your unit tests are not found and not executed as far as I can tell.

brahma712 commented 5 years ago

Its very strange.. because I see reports getting populated after I run gradlew clean build. and there is an index.html that is generated under build/reports/tests/test. I am wondering if that means that tells you anything about the sourceSet not being the default. I have generally seen the report under build/reports/test? may be I am wrong.

Alex-Vol-SV commented 5 years ago

Newer Gradle versions have changed the reports location for unit tests to exist under build/reports/tests/test. Older versions of Gradle had build/reports/test.

As I said, I do not use any specific sourceSets in my builds but I never nest more than one level either. There is a top container project with all submodules under one top level submodules directory. So, there may be something tricky about your multilevel subproject builds that requires additional code in the top level to properly handle the layered module directories.

brahma712 commented 5 years ago

thats the only possibility left .. I have a high level container which contains submodules that are contains which in turn contain more modules and these modules have code.

So for example, root ModuleAcontains modules ModuleBand ModuleC. ModuleB is a container with modules X and Y. X and Y have modules in them but these have source code and tests within src/main and src/test and have their own build.gradle files. ModuleChas one single module Z. And the clover configuration works for that. I wonder if changing ModuleB to have less layers would change anything?

There is one root build.gradle file which is in ModuleA. But ModuleB and ModuleC don't have their own build.gradle files.

Does the above structure make sense? May be because of this structure, additional sourceSets are required? Or some other configuration that I don't know of.

Alex-Vol-SV commented 5 years ago

I suspect your plugins are not applied uniformly because of the multilayer submodules. I have not tried to experiment with this level of nesting before, I may do a quick example project like yours to better understand the issue. It does seem to be related to the nesting level.

To satisfy my own curiosity I created a super simple project with a build.gradle and settings.gradle like these:

build.gradle

println 'All Projects'
allprojects { proj ->
  println proj
}

println 'Subprojects'
subprojects { proj ->
  println proj
}

settings.gradle

rootProject.name = 'rootProj'

include 'modules:projA:projB'
include 'modules:projA:projC'
include 'modules:projD:projE'
include 'modules:projD:projF'

The results indicate that allprojects and subprojects behave as we expect them to behave.

./gradlew project -q
All Projects
root project 'rootProj'
project ':modules'
project ':modules:projA'
project ':modules:projD'
project ':modules:projA:projB'
project ':modules:projA:projC'
project ':modules:projD:projE'
project ':modules:projD:projF'
Subprojects
project ':modules'
project ':modules:projA'
project ':modules:projD'
project ':modules:projA:projB'
project ':modules:projA:projC'
project ':modules:projD:projE'
project ':modules:projD:projF'

------------------------------------------------------------
Root project
------------------------------------------------------------

Root project 'rootProj'
\--- Project ':modules'
     +--- Project ':modules:projA'
     |    +--- Project ':modules:projA:projB'
     |    \--- Project ':modules:projA:projC'
     \--- Project ':modules:projD'
          +--- Project ':modules:projD:projE'
          \--- Project ':modules:projD:projF'

To see a list of the tasks of a project, run gradlew <project-path>:tasks
For example, try running gradlew :modules:tasks
brahma712 commented 5 years ago

I want to share the dependency tree that I have with you but I cant put the proprietary stuff and classnames on here.. can I share it some other way? Pretty much the same as to what you have..

Alex-Vol-SV commented 5 years ago

I do not know if it will help and I do not have more time to sort this out for you. It does not seem like an issue with the plugin and I have other pressing things taking my time.

If you can create a small example project that has simple java classes and Spock tests with the same nesting level and causes the same issue I am willing to investigate it. Make such a project in your Github and post the link to the code here. I do not know when I might find time to dig into it but I will try. This has to be able to prove that there is an issue with the nesting so do the minimum that will mimic the layout you use and your build.gradle files and will see what I can find.

brahma712 commented 5 years ago

https://github.com/brahma3691/multi-project-test

Pretty similar. I only added tests in one module and did not add in the other but you can assume that other directories have the same structure.

Alex-Vol-SV commented 5 years ago

Your structure is quite unusual. Here are some notes.

  1. There is no need to have more than one gradle wrappper instance in a multiproject Gradle build. Only the top level needs the gradle wrapper and gradle subdirectory.
  2. Having a settings.gradle file in a submodule makes that an independent project which will not inherit settings and get injection of configuration via allprojects and subprojects.
  3. There is no need to repeat the configuration and even have build.gradle files in each submodule in a multiproject Gradle build. You can make all configuration consistent from the top level project.
  4. Applying plugins like java and groovy to projects that have no source code in them is pointless and has no functional reason.
  5. You are using inconsistent versions of groovy and you are using the groovy-all package which is not a good idea. Your main groovy dependency is 2.3.11 and yet you use spock 1.2-groovy-2.5. You should match the version of spock with the version of groovy you build against.

Perhaps you put this together in a hurry and it is not completely representing your configuration.

Alex-Vol-SV commented 5 years ago

Here is a fixed copy of your repository that actually works. https://github.com/Alex-Vol/gradle-clover-multiproject-example

The problem is that you are very inconsistent with your use of Gradle. Do not add gradle wrapper and settings.gradle in submodules. If you must add a gradlew create a script wrapper that calls the top level gradlew instead. Something like this:

@echo off
call ..\..\..\gradlew.bat %*
brahma712 commented 5 years ago

Thank you so much for taking the time to look at this. My issue roots from IntelliJ auto creating these files! I didn’t realize point#2 that you made about settings.gradle because I haven’t worked a lot with multi module projects. These modules were creators by doing letting IntelliJ set up a new module automatically for you. Thanks again I’m going to implement some changes to my project to get it to work. I appreciate your effort to help me fix this

brahma712 commented 5 years ago

And my issues are fixed! I removed the gradle wrappers and settings.gradle from each module and merged everything into one single build file at the root. One thing I found additionally is I had groovy and java under each src/main and src/test but the java folder had nothing under it - it was created by IntelliJ with the New Module creation functionality. If I removed that directory, the clover reports were generated but if I had the empty java directories the clover reports were not generating. Which I find strange. But THANK YOU SO MUCH!