2
votes

I am trying my project to change from java7 to java8. So i made changes to existing gradle extra.commons-myp.gradle script that i used for gradle 1.6.

I made change of complie to JavaCompile as it is deprecated after 2.0. I get error at test task,


    testReportDir = file("$buildDir/reports/tests/UT")
    testResultsDir = file("$buildDir/test-results/UT")

Please suggest me what i am missing. . .


    allprojects {
       apply plugin: 'java' 
       apply plugin: 'jacoco'

        tasks.withType(Compile) {
         options.debug = true
         options.compilerArgs = ["-g"]
       }

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

       }

       jacoco {
            toolVersion = "0.7.2.201409121644"
       }

       test {
         maxParallelForks = 5
         forkEvery = 50
         ignoreFailures = true

         testReportDir = file("$buildDir/reports/tests/UT")
         testResultsDir = file("$buildDir/test-results/UT")

         }

         //Following Jacoco test section is required only in Jenkins instance extra common file
         jacoco {
            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 {
            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 {        
           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 = 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('src/java')
          classDirectories =  files('build/classes/main')
      }
    }

The error you are getting is similar to the following for either of those properties:

No such property: testResultDirs for class: org.gradle.api.tasks.testing.Test_Decorated
1

1 Answers

2
votes

OK.

In Gradle 1.6 or until before 1.10 (I guess), the following properties were available to test task.

testReportDir = file("$buildDir/reports/tests/UT")
testResultsDir = file("$buildDir/test-results/UT")

As you see, the first one creates a custom reports folder (where HTML index.html file will be placed i.e. instead of using the default build/reports/tests folder, we wanted to put the index.html/with other files sitting next to this file under build/reports/tests/UT folder) and the second property creates the custom test-results folder (i.e. instead of using build/test-results folder to put Unit tests result *.xml files/folders, it'll actually put all that data in build/test-results/UT folder now).

The idea was: In Gradle 1.6, Gradle was creating the test results (.xml etc) / report files (.html etc) when you just ran: gradle clean build (as test task, ran for free i.e. build calls test task to run the Unit tests without the user calling the test task explicitly).

Now, as you were using Java7 with Gradle 1.6 < 1.9/10, things were good but as soon as you started using Java8, you may see issues that Gradle 1.6 is NOT COMPATIBLE with Java8 (due to ASM libraries and other compile time issues which comes using Java8 if any), thus you jumped from using Gradle 1.6 to Gradle 2.3 version.

PS: Gradle 2.4 is the latest one, but it'd require extra tweaks in extra global (init.d level) gradle file. I would say stick to Gradle 2.3 now.

Now, to your ?s - How to get the Custom test-results and reports folder (build/test-results/UT and build/reports/tests/UT folder created).

At this time, you are using Java8 with Gradle 2.3 (or with Java7). All it matters is now you have Gradle 2.3 (instead of 1.6).

So, what to change and how to find what to change.

  1. See Gradle docs for 2.3: https://docs.gradle.org/2.3/userguide/java_plugin.html#sec:java_test (Here you have to see and understand first, what exactly got changed from Gradle 1.6 to 2.3 in test task and how reports will be generated now).

  2. The documentation does NOT have all the fields (what Gradle can have / use) defined on their site. Don't know why, but luckily we can find out all those variables that you defined in test or testReport task (this one is a new task and was not available in Gradle 1.6).

    For ex: https://docs.gradle.org/2.3/dsl/org.gradle.api.tasks.testing.Test.html shows only the main properties or variables that you can set in test task.

    To our luck, now there are NO testReportDir or testResultsDir properties available in test task anymore (in Gradle 2.3).

    To see what all Gradle can see. See or run: gradle properties

    The above command will list all the variable/properties with values what a given Gradle x.y version can see.

  3. The new task testReport or in Gradle 2.3 has a concept that now when Gradle will run build / tests during the build and generate the .xml or .html etc files, you can collectively generate HTML report using the reports (html part) at the end after you call testReport task explicitly. This helps basically when you have a multi-module project setup and where each sub-project/modules have tests in it. If you run gradle clean build testReport it will generate the .xml and .html reports in the default location (until you specify destinationDir, testResultDirs and reportsOn properties variables in testReport task instead of test task).

Now, one would say, if I call gradle clean build testReport at command line in a multi-module project setup, you can generate .xmls and .htmls at the given location for each sub-project/module. Yes, that's correct. If we don't want, then we have to use the following property in test task (instead of testReport task) to disable the creation of html reports for each sub-project as obviously, we'll call testReport task at the end (or using test.finalizedBy testReport) to generate reports for all the tests (as mentioned in the Gradle 2.3 docs.

 test {
 ...
 .....
 reports.html.enabled = false
 ...
 .
 }

See this example: https://docs.gradle.org/2.3/userguide/java_plugin.html#sec:java_test see section 23.13.7 and example: 23.14.

subprojects {
    apply plugin: 'java'

    // Disable the test report for the individual test task
    test {
        reports.html.enabled = false
    }
}

task testReport(type: TestReport) {
    destinationDir = file("$buildDir/reports/allTests")
    // Include the results from the `test` task in all subprojects
    reportOn subprojects*.test
}

The above example is showing that, it'll create the test reports (HTML) after reading the test results (.xml/etc info) from all the sub-projects in a multi-module project structure and it'll create the resultant reports in build/tests/allTests folder.

Now, we don't have multi-module structure so we have to do the following:

1. Add a new task testReport in extra1... init.d level gradle file.

task testReport(type: TestReport) {
    destinationDir = file("$buildDir/reports/tests/UT")
    testResultDirs = fileTree("$buildDir/test-results/UT")
    reportOn test
}

2. Change test task i.e.

test {
     maxParallelForks = 5
     forkEvery = 50
     ignoreFailures = true
     //The following two properties DONT work in Gradle 2.3
     //testReportDir = file("$buildDir/reports/tests/UT")
     //testResultsDir = file("$buildDir/test-results/UT")

     //With Gradle 2.3 we now need the following line to disable HTML report creation during test run per project/sub-project as we'll take care of generating those reports by testReport task which is available in Gradle 2.3.
     reports.html.enabled = false

     //OK - it took some time, but finally I can change the test-results
     //folder which Gradle generates and uses it to put the .xml/tests results files and etc folders.
     //As there is NO way to set a property in Gradle 2.3 to change the result directory property/variable, 
     //the only way we can do it by adding the following line.
     testResultsDirName = "test-results/UT"

     //The following commented out lines are optional. Un-comment if you need to.
     //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 {
        //Following two properties/variables works ONLY with 1.6 of Gradle
        //destPath = file("$buildDir/jacoco/UT/jacocoUT.exec")
        //classDumpPath = file("$buildDir/jacoco/UT/classpathdumps")


        //Following two properties/variable works only with versions >= 1.7 version of Gradle
        destinationFile = file("$buildDir/jacoco/UT/jacocoUT.exec")
        //  classDumpFile = file("$buildDir/jacoco/UT/classpathdumps")
     }

     //Usually one should call testReport at command line while calling gradle clean build 
     // i.e. gradle clean build testReport
     // But using Gradle 2.3 finalizedBy feature, you can call testReport as soon as test task is run by Gradle during gradle clean build.
     // PS: This will bring confusion if you have a multi-module project structure as there, you should call testReport task explicitly at command line. So, comment or uncomment acc. to your use.
     finalizedBy testReport
   }

If you notice, there are variables which changed from Gradle 1.6 to Gradle 2.3 from one task to another task and the name of those variable/properties were changed a little bit too (for ex: testResultsDir to testResultDirs) and there's no testReportDir property in test task anymore but there's now destinationDir in testReport task.

Also, I'm calling testReport task after test task is complete (as test.finalizedBy testReport) to automatically call testReport task (rather than requiring a user to call it explicitly).

ANOTHER WORKAROUND, IF you don't need to make the above changes (to get what you are trying to achieve) and also don't want to run testReport task to run reports at the end then, you can also do the following. Watch carefully what is getting uncommented / commented this time.

//task testReport(type: TestReport) {
//    destinationDir = file("$buildDir/reports/tests/UT")
//    testResultDirs = fileTree("$buildDir/test-results/UT")
//    reportOn test
//}

test {
     maxParallelForks = 5
     forkEvery = 50
     ignoreFailures = true
     //The following two properties DONT work in Gradle 2.3
     //testReportDir = file("$buildDir/reports/tests/UT")
     //testResultsDir = file("$buildDir/test-results/UT")

     //With Gradle 2.3 we now need the following line to disable HTML report creation during test run per project/sub-project as we'll take care of generating those reports by testReport task which is available in Gradle 2.3.
     //This time you need to comment the following line, so that it'll actually create the reports/html file during test run.
     //reports.html.enabled = false

     doFirst {   
     //OK - it took some time, but finally I can change the test-results
     //folder which Gradle generates and uses it to put the .xml/tests results files and etc folders.
     //As there is NO way to set a property in Gradle 2.3 to change the result directory property/variable, 
     //the only way we can do it by adding the following line.
     testResultsDirName = "test-results/UT"

     //Add the following if reports.html.enable = false line is commented out OR it's not commented but value is set to "true".
     //The following line will change the default build/reports/tests folder to build/reports/tests/UT for creating html reports for Unit tests.
     testReportDirName = "tests/UT"
     }

     //The following commented out lines are optional. Un-comment if you need to.
     //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 {
        //Following two properties/variables works ONLY with 1.6 of Gradle
        //destPath = file("$buildDir/jacoco/UT/jacocoUT.exec")
        //classDumpPath = file("$buildDir/jacoco/UT/classpathdumps")


        //Following two properties/variable works only with versions >= 1.7 version of Gradle
        destinationFile = file("$buildDir/jacoco/UT/jacocoUT.exec")
        //  classDumpFile = file("$buildDir/jacoco/UT/classpathdumps")
     }

     //Usually one should call testReport at command line while calling gradle clean build 
     // i.e. gradle clean build testReport
     // But using Gradle 2.3 finalizedBy feature, you can call testReport as soon as test task is run by Gradle during gradle clean build.
     // PS: This will bring confusion if you have a multi-module project structure as there, you should call testReport task explicitly at command line. So, comment or uncomment acc. to your use.

    //Now we don't need to call "gradle clean build testReport" anymore. 
    //finalizedBy testReport
   }

As you notice in the above code that: 1. Now my global init.d level gradle file doesn't even have testReport task. 2. I have commented out this line:

//reports.html.enabled = false

3. I have added another property called: testReportDirName = "tests/UT".

testReportDirName = "tests/UTnew"

PS: Adding testReportDirName and testResultsDirName in doFirst { .. } section/wrapper is important (otherwise if you do the similar changes for integrationTest or any integration test task, then your UT folder will be created inside build/tests-results/IT folder as build/tests-results/IT/tests-results/UT folder, whenever you'll run gradle clean build; gradle integrationTest (provided you have Tomcat up/running) and again gradle clean build.

4. There's no information about using or setting the above two variables: testReportDirName and testResultsDirName in test task anywhere in Gradle docs. The only way you can find these are by running: gradle properties at command line.

OK. Hint - Hint - How will you change this for doing the same (generating results/reports file for IT (Integration Test aka integrationTest task) or acceptanceTest task etc. I will leave that for you to find out.

I tested with both approaches above.. and now it generates the .xml files under build/test-results/UT folder and reports/html files under build/reports/tests/UT folder successfully.