diff --git a/.gitignore b/.gitignore index 39e1fda..143f20e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ classes build +out .gradle *.iml diff --git a/.travis.yml b/.travis.yml index 3b53e86..1e5da93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,3 @@ language: groovy script: - - "./gradlew --info --stacktrace test" \ No newline at end of file + - "./gradlew --info --stacktrace check" \ No newline at end of file diff --git a/README.md b/README.md index 77de109..278f371 100644 --- a/README.md +++ b/README.md @@ -4,96 +4,110 @@ gradle-scoverage ================ A plugin to enable the use of Scoverage in a gradle Scala project. -Getting started ---------------- -http://plugins.gradle.org/plugin/org.scoverage +Usage +----- -This creates an additional task `testScoverage` which will run tests against instrumented code. +You can find instructions on how to apply the plugin at: http://plugins.gradle.org/plugin/org.scoverage -A further task `reportScoverage` produces XML and HTML reports for analysing test code coverage. +### Available tasks -You need to configure the version of Scoverage that will be used. This plugin should be compatible with all 1+ versions. +1. `reportScoverage`: Produces XML and HTML reports for analysing test code coverage. -```groovy -dependencies { - scoverage 'org.scoverage:scalac-scoverage-plugin_2.11:1.1.0', 'org.scoverage:scalac-scoverage-runtime_2.11:1.1.0' -} -``` +2. `aggregateScoverage`: An experimental support for aggregating coverage statistics in composite builds. -Then launch command : -`gradle reportScoverage` or `gradle checkScoverage` + When applied on a project with sub-projects, the plugin will create the aggregation task `aggregateScoverage`, which + will first generate reports for each project individually (including the parent project), and will then generate an + aggregated result based on these reports. -Available tasks ---------------- + The aggregated report will override the parent-project specific report (`parent-project/build/reports/scoverage`). -* testScoverage - Executes all tests and creates Scoverage XML report with information about code coverage -* reportScoverage - Generates reports (see below). -* aggregateScoverage - Aggregates reports from multiple sub-projects (see below). -* checkScoverage - See below. -* compileScoverageScala - Instruments code without running tests. + One can still use `reportScoverage` in order to generate a report without aggregation. -ReportScoverage ---------------- +3. `checkScoverage`: Validates coverage according status according the generated reports (aggregated or not). -You can configure output generated by `gradle reportScoverage` using flags: + `gradle checkScoverage` will automatically invoke `reportScoverage` but it won't generate aggregated reports. + In order to check coverage of aggregated reports one should use `gradle checkScoverage aggregateScoverage`. + +### Configuration -| Flag name | Default value | Description | -| ------------------------|---------------|-------------------------------------------------| -| coverageOutputCobertura | true | Enables/disables cobertura.xml file generation. | -| coverageOutputXML | true | Enables/disables scoverage XML output. | -| coverageOutputHTML | true | Enables/disables scoverage HTML output. | -| coverageDebug | false | Enables/disables scoverage debug output. | +The plugin exposes multiple options that can be configured by setting them in an `scoverage` block within the project's +build script. These options are as follows: -Aggregating Reports -------------------- +You can configure the version of Scoverage that will be used. This plugin should -There is now experimental support for aggregating coverage statistics across sub-projects. +* `scoverageVersion = ` (default `"1.3.1"`): The version of the scoverage scalac plugin. This (gradle) plugin +should be compatible with all 1+ versions. -The project hosting the aggregation task **must** be configured as the sub-projects are; -i.e. with the scoverage plugin applied and the scoverage dependencies configured. +* `scoverageScalaVersion = ` (default `"2.12"`): The scala version of the scoverage scalac plugin. This will +be overridden by the version of the `scala-library` compile dependency (if the dependency is configured). + +* `coverageOutputCobertura = ` (default `true`): Enables/disables cobertura.xml file generation (for both aggregated and non-aggregated reports). -You also have to declare this task: +* `coverageOutputXML = ` (default `true`): Enables/disables scoverage XML output (for both aggregated and non-aggregated reports). -```groovy -task aggregateScoverage(type: org.scoverage.ScoverageAggregate) -``` +* `coverageOutputHTML = ` (default `true`): Enables/disables scoverage HTML output (for both aggregated and non-aggregated reports). -This will produce a report into `build/scoverage-aggregate` directory. +* `coverageDebug = ` (default `false`): Enables/disables scoverage debug output (for both aggregated and non-aggregated reports). -Aggregation uses same flags as reporting for enabling/disabling different output types. +* `minimumRate = ` (default `0.75`): The minimum amount of coverage in decimal proportion (`1.0` == 100%) +required for the validation to pass (otherwise `checkScoverage` will fail the build). -For checking coverage of the aggregated result, configure the checkScoverage task: +* `coverageType = <"Statement" | "Branch" | "Line">` (default `"Statement"`): The type of coverage validated by the +`checkScoverage` task. For more information on the different types, please refer to the documentation of the scalac +plugin (https://github.com/scoverage/scalac-scoverage-plugin). -```groovy -checkScoverage { - reportDir = file("$buildDir/scoverage-aggregate") -} -``` +### Run without normal compilation -CheckScoverage --------------- +By default, running any of the plugin tasks will compile the code both using "normal" compilation (`compileScala`) +and using the scoverage scalac plugin (`compileScoverageScala`). -By default, when you launch `gradle checkScoverage` build fail if only 75% of statements in project is covered by tests. +In cases where you only wish to generate reports / validate coverage, but are not interested in publishing the code, +it is possible to only compile the code with the scoverage scalac plugin, thus reducing build times significantly. +In order to do so, simply add the arguments `-x compileScala` to the gradle execution. +For example: `gradle reportScoverage -x compileScala`. -To configure it as you want, add this configuration : -``` -checkScoverage { - minimumRate = 0.5 +Migration to 3.x +---------------- + +* No more `testScoverage` task; instead, `test` will run coverage whenever the build is invoked with any of the scoverage tasks. + +* No more need to declare scalac dependencies: +```groovy +// can safely delete this from build scripts +dependencies { + scoverage group: 'org.scoverage', name: 'scalac-scoverage-plugin_2.12', version: '1.3.1' + scoverage group: 'org.scoverage', name: 'scalac-scoverage-runtime_2.12', version: '1.3.1' } ``` -You can also modify type of value to check from `Statement`s to `Line`s or `Branch`es: +* All configurations are configured in `scoverage` block. For instance: +```groovy +// do this +scoverage { + minimumRate = 0.5 +} -``` +// instead of this checkScoverage { - coverageType = 'Line' minimumRate = 0.5 } ``` -``` +* No more need to declare aggregation task: +```groovy +// can safely delete this from build scripts +task aggregateScoverage(type: org.scoverage.ScoverageAggregate) checkScoverage { - coverageType = 'Branch' - minimumRate = 0.5 + reportDir = file("$buildDir/scoverage-aggregate") } ``` + +Release history +--------------- + +##### (not released yet) - 3.0.0 + +* Auto resolution of scalac plugin dependencies. +* Aggregation task declared by default. +* Deletion of non-instrumented classes, allowing for better integration with other coverage tools such as cobertura. +* Ability to execute coverage without "normal" compilation, thus reducing build times. \ No newline at end of file diff --git a/build.gradle b/build.gradle index 3a87c1e..b9fe523 100644 --- a/build.gradle +++ b/build.gradle @@ -1,25 +1,17 @@ -// First, apply the publishing plugin -buildscript { - repositories { - maven { - url "https://plugins.gradle.org/m2/" - } - } - dependencies { - classpath "com.gradle.publish:plugin-publish-plugin:0.9.10" - } -} - -apply plugin: "com.gradle.plugin-publish" -description = 'gradle-scoverage is a Gradle plugin for calculating code coverage using Scoverage' -if (project.version == 'unspecified') { - version = '2.0.0-SNAPSHOT' +plugins { + id 'java-gradle-plugin' + id "com.gradle.plugin-publish" version "0.10.0" + id "org.jetbrains.gradle.plugin.idea-ext" version "0.4.2" } repositories { - mavenCentral() + jcenter() } +group 'org.scoverage' +description = 'gradle-scoverage is a Gradle plugin for calculating code coverage using Scoverage' +version = '2.0.0-SNAPSHOT' + ext { website = 'http://scoverage.org' vcsUrl = 'https://github.com/scoverage/gradle-scoverage.git' @@ -28,24 +20,61 @@ ext { sonatypePass = System.env.SONATYPE_PASS } -apply plugin: 'idea' +gradlePlugin { + plugins { + gradleScoverage { + id = 'org.scoverage' + implementationClass = 'org.scoverage.ScoveragePlugin' + } + } +} + +pluginBundle { + website = project.website + vcsUrl = ext.vcsUrl + description = project.description + tags = ['coverage', 'scala', 'scoverage'] + plugins { + scoveragePlugin { + displayName = 'Gradle Scoverage plugin' + } + } +} + apply plugin: 'maven' apply plugin: 'groovy' -group 'org.scoverage' sourceCompatibility = '1.6' targetCompatibility = '1.6' -configurations { - scoverage - compile.extendsFrom scoverage +dependencies { + compileOnly "org.scoverage:scalac-scoverage-plugin_2.12:1.3.1" + compile group: 'commons-io', name: 'commons-io', version: '2.6' + testCompile 'junit:junit:4.12' + testCompile 'org.hamcrest:hamcrest-library:1.3' +} + +sourceSets { + functionalTest { + java.srcDir file('src/functionalTest/java') + resources.srcDir file('src/functionalTest/resources') + compileClasspath += sourceSets.main.output + configurations.testRuntime + runtimeClasspath += output + compileClasspath + } } -dependencies { - compile gradleApi() - compile localGroovy() - scoverage "org.scoverage:scalac-scoverage-plugin_2.11:1.1.1" - testCompile 'junit:junit:4.12', 'org.hamcrest:hamcrest-library:1.3' +task functionalTest(type: Test) { + description = 'Runs the functional tests.' + group = 'verification' + testClassesDirs = sourceSets.functionalTest.output.classesDirs + classpath = sourceSets.functionalTest.runtimeClasspath + mustRunAfter test +} + +check.dependsOn functionalTest + +gradlePlugin { + testSourceSets sourceSets.functionalTest } task groovydocJar(type: Jar, dependsOn: groovydoc) { @@ -58,10 +87,6 @@ task sourcesJar(type: Jar) { classifier = 'sources' } -test { - dependsOn jar -} - artifacts { archives jar archives groovydocJar @@ -75,25 +100,11 @@ if (project.properties.containsKey('signing.keyId')) { } } -pluginBundle { - website = project.website - vcsUrl = project.vcsUrl - description = project.description - tags = ['coverage', 'scala', 'scoverage'] - withDependencies { it.clear() } - plugins { - scoveragePlugin { - id = 'org.scoverage' - displayName = 'Gradle Scoverage plugin' - } - } -} - uploadArchives { repositories { mavenDeployer { if (project.properties.containsKey('signing.keyId')) { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } } snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots') { @@ -132,8 +143,30 @@ uploadArchives { developer { id 'D-Roch' } + developer { + id 'eyalroth' + } } } } } } + +// see https://stackoverflow.com/questions/44679007 +task fixIdeaPluginClasspath { + doFirst { + configure(tasks.pluginUnderTestMetadata) { + def ideaClassesPath = project.buildDir.toPath().resolveSibling("out").resolve("production") + def newClasspath = pluginClasspath as List + newClasspath.add(0, ideaClassesPath) + pluginClasspath.setFrom(newClasspath) + } + } +} +pluginUnderTestMetadata.mustRunAfter(fixIdeaPluginClasspath) + +idea.project.settings { + taskTriggers { + beforeBuild fixIdeaPluginClasspath, pluginUnderTestMetadata + } +} \ No newline at end of file diff --git a/init-scoverage.gradle b/init-scoverage.gradle deleted file mode 100644 index 0d7837a..0000000 --- a/init-scoverage.gradle +++ /dev/null @@ -1,7 +0,0 @@ -gradle.beforeProject { p -> - p.ext { - scoverageVersion = '1.1.1' - scoverageLib = ["org.scoverage:scalac-scoverage-plugin_2.11:${scoverageVersion}", - "org.scoverage:scalac-scoverage-runtime_2.11:${scoverageVersion}"] - } -} diff --git a/src/functionalTest/java/org.scoverage/ScalaJavaMultiModuleTest.java b/src/functionalTest/java/org.scoverage/ScalaJavaMultiModuleTest.java new file mode 100644 index 0000000..0c6156e --- /dev/null +++ b/src/functionalTest/java/org.scoverage/ScalaJavaMultiModuleTest.java @@ -0,0 +1,65 @@ +package org.scoverage; + +import org.gradle.testkit.runner.TaskOutcome; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; + +public class ScalaJavaMultiModuleTest extends ScoverageFunctionalTest { + + public ScalaJavaMultiModuleTest() { + super("scala-java-multi-module"); + } + + @Test + public void checkAndAggregateScoverage() throws Exception { + + AssertableBuildResult result = run("clean", ScoveragePlugin.getCHECK_NAME(), + ScoveragePlugin.getAGGREGATE_NAME()); + + result.assertTaskOutcome("java_only:" + ScoveragePlugin.getCOMPILE_NAME(), TaskOutcome.NO_SOURCE); + + result.assertTaskSkipped(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("scala_only:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("mixed_scala_java:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSkipped("java_only:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("scala_only:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("mixed_scala_java:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSkipped("java_only:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getAGGREGATE_NAME()); + + assertAllReportFilesExist(); + assertCoverage(100.0); + } + + private void assertAllReportFilesExist() { + + Assert.assertTrue(resolve(reportDir(), "index.html").exists()); + + assertScalaOnlyReportFilesExist(); + assertMixedScalaJavaReportFilesExist(); + assertAggregationFilesExist(); + } + + private void assertAggregationFilesExist() { + + Assert.assertTrue(resolve(reportDir(), "scala_only/src/main/scala/org/hello/WorldScalaOnly.scala.html").exists()); + Assert.assertTrue(resolve(reportDir(), "mixed_scala_java/src/main/scala/org/hello/WorldScala.scala.html").exists()); + } + + private void assertScalaOnlyReportFilesExist() { + + File reportDir = reportDir(projectDir().toPath().resolve("scala_only").toFile()); + Assert.assertTrue(resolve(reportDir, "index.html").exists()); + Assert.assertTrue(resolve(reportDir, "src/main/scala/org/hello/WorldScalaOnly.scala.html").exists()); + } + + private void assertMixedScalaJavaReportFilesExist() { + + File reportDir = reportDir(projectDir().toPath().resolve("mixed_scala_java").toFile()); + Assert.assertTrue(resolve(reportDir, "index.html").exists()); + Assert.assertTrue(resolve(reportDir, "src/main/scala/org/hello/WorldScala.scala.html").exists()); + } +} diff --git a/src/functionalTest/java/org.scoverage/ScalaMultiModuleCrossVersionTest.java b/src/functionalTest/java/org.scoverage/ScalaMultiModuleCrossVersionTest.java new file mode 100644 index 0000000..224ef34 --- /dev/null +++ b/src/functionalTest/java/org.scoverage/ScalaMultiModuleCrossVersionTest.java @@ -0,0 +1,59 @@ +package org.scoverage; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; + +public class ScalaMultiModuleCrossVersionTest extends ScoverageFunctionalTest { + + public ScalaMultiModuleCrossVersionTest() { + super("scala-multi-module-cross-version"); + } + + @Test + public void checkAndAggregateScoverage() throws Exception { + + AssertableBuildResult result = run("clean", ScoveragePlugin.getCHECK_NAME(), + ScoveragePlugin.getAGGREGATE_NAME()); + + result.assertTaskSkipped(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("2_11:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("2_12:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("2_11:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("2_12:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getAGGREGATE_NAME()); + + assertAllReportFilesExist(); + assertCoverage(100.0); + } + + private void assertAllReportFilesExist() { + + assert211ReportFilesExist(); + assert212ReportFilesExist(); + assertAggregationFilesExist(); + } + + private void assertAggregationFilesExist() { + + Assert.assertTrue(resolve(reportDir(), "index.html").exists()); + Assert.assertTrue(resolve(reportDir(), "2_11/src/main/scala/org/hello/World211.scala.html").exists()); + Assert.assertTrue(resolve(reportDir(), "2_12/src/main/scala/org/hello/World212.scala.html").exists()); + } + + private void assert211ReportFilesExist() { + + File reportDir = reportDir(projectDir().toPath().resolve("2_11").toFile()); + Assert.assertTrue(resolve(reportDir, "index.html").exists()); + Assert.assertTrue(resolve(reportDir, "src/main/scala/org/hello/World211.scala.html").exists()); + } + + private void assert212ReportFilesExist() { + + File reportDir = reportDir(projectDir().toPath().resolve("2_12").toFile()); + Assert.assertTrue(resolve(reportDir, "index.html").exists()); + Assert.assertTrue(resolve(reportDir, "src/main/scala/org/hello/World212.scala.html").exists()); + } +} diff --git a/src/functionalTest/java/org.scoverage/ScalaMultiModuleTest.java b/src/functionalTest/java/org.scoverage/ScalaMultiModuleTest.java new file mode 100644 index 0000000..5818ca5 --- /dev/null +++ b/src/functionalTest/java/org.scoverage/ScalaMultiModuleTest.java @@ -0,0 +1,294 @@ +package org.scoverage; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; + +public class ScalaMultiModuleTest extends ScoverageFunctionalTest { + + public ScalaMultiModuleTest() { + super("scala-multi-module"); + } + + @Test + public void reportScoverage() { + + AssertableBuildResult result = dryRun("clean", ScoveragePlugin.getREPORT_NAME()); + + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("common:" + ScoveragePlugin.getREPORT_NAME()); + } + + @Test + public void reportScoverageOnlyRoot() { + + AssertableBuildResult result = dryRun("clean", ":" + ScoveragePlugin.getREPORT_NAME()); + + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("common:" + ScoveragePlugin.getREPORT_NAME()); + } + + @Test + public void reportScoverageOnlyA() { + + AssertableBuildResult result = dryRun("clean", ":a:" + ScoveragePlugin.getREPORT_NAME()); + + result.assertTaskDoesntExist(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("common:" + ScoveragePlugin.getREPORT_NAME()); + } + + @Test + public void aggregateScoverage() { + + AssertableBuildResult result = dryRun("clean", ScoveragePlugin.getAGGREGATE_NAME()); + + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists(ScoveragePlugin.getAGGREGATE_NAME()); + result.assertTaskExists("common:" + ScoveragePlugin.getREPORT_NAME()); + } + + @Test + public void checkScoverage() { + + AssertableBuildResult result = dryRun("clean", ScoveragePlugin.getCHECK_NAME()); + + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskExists("b:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskExists("common:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + } + + @Test + public void checkScoverageOnlyRoot() { + + AssertableBuildResult result = dryRun("clean", ":" + ScoveragePlugin.getCHECK_NAME()); + + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist("a:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + } + + @Test + public void checkScoverageOnlyA() { + + AssertableBuildResult result = dryRun("clean", ":a:" + ScoveragePlugin.getCHECK_NAME()); + + result.assertTaskDoesntExist(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist("common:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + } + + @Test + public void checkAndAggregateScoverage() throws Exception { + + AssertableBuildResult result = run("clean", ScoveragePlugin.getCHECK_NAME(), + ScoveragePlugin.getAGGREGATE_NAME()); + + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getAGGREGATE_NAME()); + + assertAllReportFilesExist(); + assertCoverage(100.0); + } + + @Test + public void checkScoverageWithoutCoverageInRoot() throws Exception { + + AssertableBuildResult result = runAndFail("clean", ScoveragePlugin.getCHECK_NAME(), + "test", + "--tests", "org.hello.TestNothingSuite", + "--tests", "org.hello.a.WorldASuite", + "--tests", "org.hello.b.WorldBSuite", + "--tests", "org.hello.common.WorldCommonSuite"); + + result.assertTaskFailed(ScoveragePlugin.getCHECK_NAME()); + + assertRootReportFilesExist(); + assertCoverage(0.0); + } + + @Test + public void checkScoverageWithoutCoverageInA() throws Exception { + + AssertableBuildResult result = runAndFail("clean", ScoveragePlugin.getCHECK_NAME(), + "test", + "--tests", "org.hello.a.TestNothingASuite", + "--tests", "org.hello.WorldSuite", + "--tests", "org.hello.b.WorldBSuite", + "--tests", "org.hello.common.WorldCommonSuite"); + + result.assertTaskFailed("a:" + ScoveragePlugin.getCHECK_NAME()); + + assertAReportFilesExist(); + assertCoverage(0.0, reportDir(projectDir().toPath().resolve("a").toFile())); + } + + @Test + public void checkScoverageWithoutNormalCompilationAndWithoutCoverageInCommon() throws Exception { + + AssertableBuildResult result = runAndFail("clean", + ":a:test", + ":common:test", "--tests", "org.hello.common.TestNothingCommonSuite", + "-x", "compileScala", + ScoveragePlugin.getCHECK_NAME()); + + result.assertTaskFailed("common:" + ScoveragePlugin.getCHECK_NAME()); + + assertCommonReportFilesExist(); + assertCoverage(0.0, reportDir(projectDir().toPath().resolve("common").toFile())); + } + + @Test + public void checkAndAggregateScoverageWithoutCoverageInRoot() throws Exception { + + // should pass as the check on the root is for the aggregation (which covers > 50%) + + AssertableBuildResult result = run("clean", ScoveragePlugin.getCHECK_NAME(), + ScoveragePlugin.getAGGREGATE_NAME(), "test", + "--tests", "org.hello.TestNothingSuite", + "--tests", "org.hello.a.WorldASuite", + "--tests", "org.hello.b.WorldBSuite", + "--tests", "org.hello.common.WorldCommonSuite"); + + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getAGGREGATE_NAME()); + + assertAllReportFilesExist(); + assertCoverage(87.5); + } + + @Test + public void checkAndAggregateScoverageWithoutCoverageInAll() throws Exception { + + AssertableBuildResult result = runAndFail("clean", ScoveragePlugin.getCHECK_NAME(), + ScoveragePlugin.getAGGREGATE_NAME(), "test", + "--tests", "org.hello.TestNothingSuite", + "--tests", "org.hello.a.TestNothingASuite", + "--tests", "org.hello.b.TestNothingBSuite", + "--tests", "org.hello.common.TestNothingCommonSuite"); + + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getAGGREGATE_NAME()); + result.assertTaskFailed(ScoveragePlugin.getCHECK_NAME()); + + assertAllReportFilesExist(); + assertCoverage(0.0); + } + + @Test + public void aggregateScoverageWithoutNormalCompilation() throws Exception { + + AssertableBuildResult result = run("clean", ScoveragePlugin.getAGGREGATE_NAME(), + "-x", "compileScala"); + + result.assertTaskSkipped("compileScala"); + result.assertTaskSkipped("a:compileScala"); + result.assertTaskSkipped("b:compileScala"); + result.assertTaskSkipped("common:compileScala"); + result.assertTaskSucceeded(ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getAGGREGATE_NAME()); + + assertAllReportFilesExist(); + assertCoverage(100.0); + + Assert.assertTrue(resolve(buildDir(resolve(projectDir(), "a")), "classes/scala/main/org/hello/a/WorldA.class").exists()); + Assert.assertFalse(resolve(buildDir(resolve(projectDir(), "a")), "classes/scala/scoverage/org/hello/a/WorldA.class").exists()); + + Assert.assertTrue(resolve(buildDir(resolve(projectDir(), "b")), "classes/scala/main/org/hello/b/WorldB.class").exists()); + Assert.assertFalse(resolve(buildDir(resolve(projectDir(), "b")), "classes/scala/scoverage/org/hello/b/WorldB.class").exists()); + + Assert.assertTrue(resolve(buildDir(resolve(projectDir(), "common")), "classes/scala/main/org/hello/common/WorldCommon.class").exists()); + Assert.assertFalse(resolve(buildDir(resolve(projectDir(), "common")), "classes/scala/scoverage/org/hello/common/WorldCommon.class").exists()); + } + + private void assertAllReportFilesExist() { + + assertRootReportFilesExist(); + assertAReportFilesExist(); + assertBReportFilesExist(); + assertCommonReportFilesExist(); + assertAggregationFilesExist(); + } + + private void assertAggregationFilesExist() { + + Assert.assertTrue(resolve(reportDir(), "a/src/main/scala/org/hello/a/WorldA.scala.html").exists()); + Assert.assertTrue(resolve(reportDir(), "b/src/main/scala/org/hello/b/WorldB.scala.html").exists()); + Assert.assertTrue(resolve(reportDir(), "common/src/main/scala/org/hello/common/WorldCommon.scala.html").exists()); + } + + private void assertRootReportFilesExist() { + + Assert.assertTrue(resolve(reportDir(), "index.html").exists()); + Assert.assertTrue(resolve(reportDir(), "src/main/scala/org/hello/World.scala.html").exists()); + } + + private void assertAReportFilesExist() { + + File reportDir = reportDir(projectDir().toPath().resolve("a").toFile()); + Assert.assertTrue(resolve(reportDir, "index.html").exists()); + Assert.assertTrue(resolve(reportDir, "src/main/scala/org/hello/a/WorldA.scala.html").exists()); + } + + private void assertBReportFilesExist() { + + File reportDir = reportDir(projectDir().toPath().resolve("b").toFile()); + Assert.assertTrue(resolve(reportDir, "index.html").exists()); + Assert.assertTrue(resolve(reportDir, "src/main/scala/org/hello/b/WorldB.scala.html").exists()); + } + + private void assertCommonReportFilesExist() { + + File reportDir = reportDir(projectDir().toPath().resolve("common").toFile()); + Assert.assertTrue(resolve(reportDir, "index.html").exists()); + Assert.assertTrue(resolve(reportDir, "src/main/scala/org/hello/common/WorldCommon.scala.html").exists()); + } +} diff --git a/src/functionalTest/java/org.scoverage/ScalaSingleModuleTest.java b/src/functionalTest/java/org.scoverage/ScalaSingleModuleTest.java new file mode 100644 index 0000000..f93e184 --- /dev/null +++ b/src/functionalTest/java/org.scoverage/ScalaSingleModuleTest.java @@ -0,0 +1,141 @@ +package org.scoverage; + +import org.junit.Assert; +import org.junit.Test; + +public class ScalaSingleModuleTest extends ScoverageFunctionalTest { + + public ScalaSingleModuleTest() { + super("scala-single-module"); + } + + @Test + public void test() { + + AssertableBuildResult result = dryRun("clean", "test"); + + result.assertTaskDoesntExist(ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getCHECK_NAME()); + } + + @Test + public void build() { + + AssertableBuildResult result = dryRun("clean", "build"); + + result.assertTaskDoesntExist(ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getCHECK_NAME()); + } + + @Test + public void reportScoverage() { + + AssertableBuildResult result = dryRun("clean", ScoveragePlugin.getREPORT_NAME()); + + result.assertTaskExists(ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getCHECK_NAME()); + } + + @Test + public void aggregateScoverage() { + + AssertableBuildResult result = runAndFail("clean", ScoveragePlugin.getAGGREGATE_NAME()); + + result.assertNoTasks(); + } + + @Test + public void checkScoverage() throws Exception { + + AssertableBuildResult result = run("clean", ScoveragePlugin.getCHECK_NAME()); + + result.assertTaskSucceeded(ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + + assertReportFilesExist(); + assertCoverage(50.0); + } + + @Test + public void checkScoverageFails() throws Exception { + + AssertableBuildResult result = runAndFail("clean", ScoveragePlugin.getCHECK_NAME(), + "test", "--tests", "org.hello.TestNothingSuite"); + + result.assertTaskSucceeded(ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskFailed(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + + assertReportFilesExist(); + assertCoverage(0.0); + } + + @Test + public void reportScoverageWithExcludedClasses() throws Exception { + + AssertableBuildResult result = run("clean", ScoveragePlugin.getREPORT_NAME(), + "-PexcludedFile=.*"); + + result.assertTaskSucceeded(ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + + Assert.assertTrue(resolve(reportDir(), "index.html").exists()); + Assert.assertFalse(resolve(reportDir(), "src/main/scala/org/hello/World.scala.html").exists()); + assertCoverage(100.0); // coverage is 100 since no classes are covered + + // compiled class should exist in the default classes directory, but not in scoverage + Assert.assertTrue(resolve(buildDir(), "classes/scala/main/org/hello/World.class").exists()); + Assert.assertFalse(resolve(buildDir(), "classes/scala/scoverage/org/hello/World.class").exists()); + } + + @Test + public void reportScoverageWithoutNormalCompilation() throws Exception { + + AssertableBuildResult result = run("clean", ScoveragePlugin.getREPORT_NAME(), + "-x", "compileScala"); + + result.assertTaskSkipped("compileScala"); + result.assertTaskSucceeded(ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + + assertReportFilesExist(); + assertCoverage(50.0); + + Assert.assertTrue(resolve(buildDir(), "classes/scala/main/org/hello/World.class").exists()); + Assert.assertFalse(resolve(buildDir(), "classes/scala/scoverage/org/hello/World.class").exists()); + } + + @Test + public void reportScoverageWithoutNormalCompilationAndWithExcludedClasses() throws Exception { + + AssertableBuildResult result = run("clean", ScoveragePlugin.getREPORT_NAME(), + "-PexcludedFile=.*", "-x", "compileScala"); + + Assert.assertTrue(resolve(reportDir(), "index.html").exists()); + Assert.assertFalse(resolve(reportDir(), "src/main/scala/org/hello/World.scala.html").exists()); + assertCoverage(100.0); // coverage is 100 since no classes are covered + + // compiled class should exist in the default classes directory, but not in scoverage + Assert.assertTrue(resolve(buildDir(), "classes/scala/main/org/hello/World.class").exists()); + Assert.assertFalse(resolve(buildDir(), "classes/scala/scoverage/org/hello/World.class").exists()); + } + + private void assertReportFilesExist() { + + Assert.assertTrue(resolve(reportDir(), "index.html").exists()); + Assert.assertTrue(resolve(reportDir(), "src/main/scala/org/hello/World.scala.html").exists()); + } +} \ No newline at end of file diff --git a/src/functionalTest/java/org.scoverage/ScalaSingleModuleWithDepdencyManagerTest.java b/src/functionalTest/java/org.scoverage/ScalaSingleModuleWithDepdencyManagerTest.java new file mode 100644 index 0000000..f8548fe --- /dev/null +++ b/src/functionalTest/java/org.scoverage/ScalaSingleModuleWithDepdencyManagerTest.java @@ -0,0 +1,31 @@ +package org.scoverage; + +import org.junit.Assert; +import org.junit.Test; + +public class ScalaSingleModuleWithDepdencyManagerTest extends ScoverageFunctionalTest { + + public ScalaSingleModuleWithDepdencyManagerTest() { + super("scala-single-module-dependency-manager"); + } + + @Test + public void checkScoverage() throws Exception { + + AssertableBuildResult result = run("clean", ScoveragePlugin.getCHECK_NAME()); + + result.assertTaskSucceeded(ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + + assertReportFilesExist(); + assertCoverage(100.0); + } + + private void assertReportFilesExist() { + + Assert.assertTrue(resolve(reportDir(), "index.html").exists()); + Assert.assertTrue(resolve(reportDir(), "src/main/scala/org/hello/World.scala.html").exists()); + } +} \ No newline at end of file diff --git a/src/functionalTest/java/org.scoverage/ScoverageFunctionalTest.java b/src/functionalTest/java/org.scoverage/ScoverageFunctionalTest.java new file mode 100644 index 0000000..af14ce5 --- /dev/null +++ b/src/functionalTest/java/org.scoverage/ScoverageFunctionalTest.java @@ -0,0 +1,201 @@ +package org.scoverage; + +import groovy.util.Node; +import groovy.util.XmlParser; +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.BuildTask; +import org.gradle.testkit.runner.GradleRunner; +import org.gradle.testkit.runner.TaskOutcome; +import org.junit.Assert; +import org.xml.sax.SAXException; + +import java.io.File; +import java.io.IOException; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +import static org.hamcrest.number.IsCloseTo.closeTo; +import static org.junit.Assert.assertThat; + +public abstract class ScoverageFunctionalTest { + + private final String projectName; + private final GradleRunner runner; + private final XmlParser parser; + + protected ScoverageFunctionalTest(String projectName) { + + this.projectName = projectName; + this.runner = GradleRunner.create() + .withProjectDir(projectDir()) + .withPluginClasspath() + .forwardOutput(); + + try { + this.parser = new XmlParser(); + parser.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + protected File projectDir() { + + return new File("src/functionalTest/resources/projects/" + projectName); + } + + protected File buildDir() { + + return buildDir(projectDir()); + } + + protected File buildDir(File projectDir) { + + return projectDir.toPath().resolve("build").toFile(); + } + + protected File reportDir() { + + return reportDir(projectDir()); + } + + protected File reportDir(File projectDir) { + + return buildDir(projectDir).toPath().resolve(ScoveragePlugin.getDEFAULT_REPORT_DIR()).toFile(); + } + + protected AssertableBuildResult run(String... arguments) { + + configureArguments(arguments); + return new AssertableBuildResult(runner.build()); + } + + protected AssertableBuildResult runAndFail(String... arguments) { + + configureArguments(arguments); + return new AssertableBuildResult(runner.buildAndFail()); + } + + protected AssertableBuildResult dryRun(String... arguments) { + + List withDryArgument = new ArrayList(Arrays.asList(arguments)); + withDryArgument.add("--dry-run"); + return run(withDryArgument.toArray(new String[]{})); + } + + protected void assertCoverage(Double expected) throws Exception { + + assertCoverage(expected, reportDir()); + } + + protected void assertCoverage(Double expected, File reportDir) throws Exception { + + assertThat(coverage(reportDir, CoverageType.Statement), closeTo(expected, 1.0)); + assertThat(coverage(reportDir, CoverageType.Line), closeTo(expected, 1.0)); + } + + protected File resolve(File file, String relativePath) { + + return file.toPath().resolve(relativePath).toFile(); + } + + private Double coverage(File reportDir, CoverageType coverageType) throws IOException, SAXException, ParseException { + + File reportFile = reportDir.toPath().resolve(coverageType.getFileName()).toFile(); + Node xml = parser.parse(reportFile); + Object attribute = xml.attribute(coverageType.getParamName()); + double rawValue = NumberFormat.getInstance().parse(attribute.toString()).doubleValue(); + return coverageType.normalize(rawValue) * 100.0; + } + + private void configureArguments(String... arguments) { + + List fullArguments = new ArrayList(); + + fullArguments.add("-PscalaVersionMajor=2"); + fullArguments.add("-PscalaVersionMinor=12"); + fullArguments.add("-PscalaVersionBuild=8"); + fullArguments.add("-PjunitVersion=5.3.2"); + fullArguments.add("-PjunitPlatformVersion=1.3.2"); + fullArguments.add("-PscalatestVersion=3.0.5"); + fullArguments.addAll(Arrays.asList(arguments)); + + runner.withArguments(fullArguments); + } + + protected static class AssertableBuildResult { + + private final BuildResult result; + + private AssertableBuildResult(BuildResult result) { + + this.result = result; + } + + public BuildResult getResult() { + + return result; + } + + public void assertNoTasks() { + + Assert.assertEquals(0, result.getTasks().size()); + } + + public void assertTaskExists(String taskName) { + + Assert.assertTrue(taskExists(taskName)); + } + + public void assertTaskDoesntExist(String taskName) { + + Assert.assertFalse(taskExists(taskName)); + } + + public void assertTaskSkipped(String taskName) { + + BuildTask task = getTask(taskName); + Assert.assertTrue(task == null || task.getOutcome() == TaskOutcome.SKIPPED); + } + + public void assertTaskSucceeded(String taskName) { + + assertTaskOutcome(taskName, TaskOutcome.SUCCESS); + } + + public void assertTaskFailed(String taskName) { + + assertTaskOutcome(taskName, TaskOutcome.FAILED); + } + + public void assertTaskOutcome(String taskName, TaskOutcome outcome) { + + BuildTask task = getTask(taskName); + Assert.assertNotNull(task); + Assert.assertEquals(outcome, task.getOutcome()); + + } + + private BuildTask getTask(String taskName) { + + return result.task(fullTaskName(taskName)); + } + + private String fullTaskName(String taskName) { + + return ":" + taskName; + } + + private boolean taskExists(String taskName) { + + Pattern regex = Pattern.compile("^(> Task )?" + fullTaskName(taskName), Pattern.MULTILINE); + return regex.matcher(result.getOutput()).find(); + } + } +} + diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/build.gradle b/src/functionalTest/resources/projects/scala-java-multi-module/build.gradle new file mode 100644 index 0000000..b486ee1 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/build.gradle @@ -0,0 +1,32 @@ +plugins { + id 'org.scoverage' apply false +} + +allprojects { + repositories { + jcenter() + } +} + +description = 'a multi-module Scala and Java project that builds successfully with 100% coverage' + +apply plugin: 'org.scoverage' + +allprojects { + + dependencies { + testCompile group: 'org.junit.platform', name: 'junit-platform-runner', version: junitPlatformVersion + } + + test { + useJUnitPlatform() + } + + scoverage { + minimumRate = 0.5 + } +} + +scoverage { + minimumRate = 0.5 +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/java_only/build.gradle b/src/functionalTest/resources/projects/scala-java-multi-module/java_only/build.gradle new file mode 100644 index 0000000..1cb42eb --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/java_only/build.gradle @@ -0,0 +1,6 @@ +apply plugin: 'java' + +dependencies { + + testRuntime group: 'org.junit.vintage', name: 'junit-vintage-engine', version: junitVersion +} diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/java_only/src/main/java/org/hello/WorldJavaOnly.java b/src/functionalTest/resources/projects/scala-java-multi-module/java_only/src/main/java/org/hello/WorldJavaOnly.java new file mode 100644 index 0000000..95c85de --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/java_only/src/main/java/org/hello/WorldJavaOnly.java @@ -0,0 +1,9 @@ +package org.hello; + +public class WorldJavaOnly { + + public String foo() { + String s = "java_only" + "a"; + return s; + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/java_only/src/test/java/org/hello/WorldJavaOnlyTest.java b/src/functionalTest/resources/projects/scala-java-multi-module/java_only/src/test/java/org/hello/WorldJavaOnlyTest.java new file mode 100644 index 0000000..68fd33d --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/java_only/src/test/java/org/hello/WorldJavaOnlyTest.java @@ -0,0 +1,11 @@ +package org.hello; + +import org.junit.Test; + +public class WorldJavaOnlyTest { + + @Test + public void foo() { + new WorldJavaOnly().foo(); + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/build.gradle b/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/build.gradle new file mode 100644 index 0000000..9d6a7ab --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/build.gradle @@ -0,0 +1,19 @@ +apply plugin: 'java' +apply plugin: 'scala' +apply plugin: 'org.scoverage' + +dependencies { + compile group: 'org.scala-lang', name: 'scala-library', version: "${scalaVersionMajor}.${scalaVersionMinor}.${scalaVersionBuild}" + + testRuntime group: 'org.junit.vintage', name: 'junit-vintage-engine', version: junitVersion + + testCompile group: 'org.scalatest', name: "scalatest_${scalaVersionMajor}.${scalaVersionMinor}", version: scalatestVersion +} + +// A common practice in mixed java/scala modules to make Java code able to import Scala code +ext.configureSources = { set, name -> + set.scala.srcDir("src/$name/java") + set.java.srcDirs = [] +} +configureSources(sourceSets.main, 'main') +configureSources(sourceSets.test, 'test') \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/main/java/org/hello/WorldJava.java b/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/main/java/org/hello/WorldJava.java new file mode 100644 index 0000000..bcfd8cf --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/main/java/org/hello/WorldJava.java @@ -0,0 +1,9 @@ +package org.hello; + +public class WorldJava { + + public String foo() { + String s = "java" + "a"; + return s; + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/main/scala/org/hello/WorldScala.scala b/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/main/scala/org/hello/WorldScala.scala new file mode 100644 index 0000000..8cdded1 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/main/scala/org/hello/WorldScala.scala @@ -0,0 +1,9 @@ +package org.hello + +class WorldScala { + + def foo(): String = { + val s = "scala" + "a" + s + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/test/java/org/hello/WorldJavaTest.java b/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/test/java/org/hello/WorldJavaTest.java new file mode 100644 index 0000000..a88e452 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/test/java/org/hello/WorldJavaTest.java @@ -0,0 +1,11 @@ +package org.hello; + +import org.junit.Test; + +public class WorldJavaTest { + + @Test + public void foo() { + new WorldJava().foo(); + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/test/scala/org/hello/WorldScalaSuite.scala b/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/test/scala/org/hello/WorldScalaSuite.scala new file mode 100644 index 0000000..4244420 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/mixed_scala_java/src/test/scala/org/hello/WorldScalaSuite.scala @@ -0,0 +1,13 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldScalaSuite extends FunSuite { + + test("foo") { + new WorldScala().foo() + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/scala_only/build.gradle b/src/functionalTest/resources/projects/scala-java-multi-module/scala_only/build.gradle new file mode 100644 index 0000000..97f6ee6 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/scala_only/build.gradle @@ -0,0 +1,10 @@ +apply plugin: 'scala' +apply plugin: 'org.scoverage' + +dependencies { + compile group: 'org.scala-lang', name: 'scala-library', version: "${scalaVersionMajor}.${scalaVersionMinor}.${scalaVersionBuild}" + + testRuntime group: 'org.junit.vintage', name: 'junit-vintage-engine', version: junitVersion + + testCompile group: 'org.scalatest', name: "scalatest_${scalaVersionMajor}.${scalaVersionMinor}", version: scalatestVersion +} diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/scala_only/src/main/scala/org/hello/WorldScalaOnly.scala b/src/functionalTest/resources/projects/scala-java-multi-module/scala_only/src/main/scala/org/hello/WorldScalaOnly.scala new file mode 100644 index 0000000..268c5a5 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/scala_only/src/main/scala/org/hello/WorldScalaOnly.scala @@ -0,0 +1,9 @@ +package org.hello + +class WorldScalaOnly { + + def foo(): String = { + val s = "scala_only" + "a" + s + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/scala_only/src/test/scala/org/hello/WorldScalaOnlySuite.scala b/src/functionalTest/resources/projects/scala-java-multi-module/scala_only/src/test/scala/org/hello/WorldScalaOnlySuite.scala new file mode 100644 index 0000000..7601021 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/scala_only/src/test/scala/org/hello/WorldScalaOnlySuite.scala @@ -0,0 +1,13 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldScalaOnlySuite extends FunSuite { + + test("foo") { + new WorldScalaOnly().foo() + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-java-multi-module/settings.gradle b/src/functionalTest/resources/projects/scala-java-multi-module/settings.gradle new file mode 100644 index 0000000..d8268de --- /dev/null +++ b/src/functionalTest/resources/projects/scala-java-multi-module/settings.gradle @@ -0,0 +1 @@ +include 'java_only', 'scala_only', 'mixed_scala_java' \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_11/build.gradle b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_11/build.gradle new file mode 100644 index 0000000..5421d5a --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_11/build.gradle @@ -0,0 +1,4 @@ +dependencies { + compile group: 'org.scala-lang', name: 'scala-library', version: "2.11.12" + testCompile group: 'org.scalatest', name: "scalatest_2.11", version: scalatestVersion +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_11/src/main/scala/org/hello/World211.scala b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_11/src/main/scala/org/hello/World211.scala new file mode 100644 index 0000000..7c7f57b --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_11/src/main/scala/org/hello/World211.scala @@ -0,0 +1,9 @@ +package org.hello + +class World211 { + + def foo(): String = { + val s = "2" + "11" + s + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_11/src/test/scala/org/hello/World211Suite.scala b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_11/src/test/scala/org/hello/World211Suite.scala new file mode 100644 index 0000000..f872840 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_11/src/test/scala/org/hello/World211Suite.scala @@ -0,0 +1,13 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class World211Suite extends FunSuite { + + test("foo") { + new World211().foo() + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_12/build.gradle b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_12/build.gradle new file mode 100644 index 0000000..0a8112a --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_12/build.gradle @@ -0,0 +1,4 @@ +dependencies { + compile group: 'org.scala-lang', name: 'scala-library', version: "2.12.8" + testCompile group: 'org.scalatest', name: "scalatest_2.12", version: scalatestVersion +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_12/src/main/scala/org/hello/World212.scala b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_12/src/main/scala/org/hello/World212.scala new file mode 100644 index 0000000..0968efa --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_12/src/main/scala/org/hello/World212.scala @@ -0,0 +1,9 @@ +package org.hello + +class World212 { + + def foo(): String = { + val s = "2" + "12" + s + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_12/src/test/scala/org/hello/World212Suite.scala b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_12/src/test/scala/org/hello/World212Suite.scala new file mode 100644 index 0000000..cd26ad3 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-cross-version/2_12/src/test/scala/org/hello/World212Suite.scala @@ -0,0 +1,13 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class World212Suite extends FunSuite { + + test("foo") { + new World212().foo() + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module-cross-version/build.gradle b/src/functionalTest/resources/projects/scala-multi-module-cross-version/build.gradle new file mode 100644 index 0000000..4a024a0 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-cross-version/build.gradle @@ -0,0 +1,36 @@ +plugins { + id 'org.scoverage' +} + +allprojects { + repositories { + jcenter() + } +} + +description = 'a multi-module Scala project with multiple Scala versions that builds successfully with 100% coverage' + +allprojects { + + apply plugin: 'java' + apply plugin: 'scala' + + dependencies { + testRuntime group: 'org.junit.vintage', name: 'junit-vintage-engine', version: junitVersion + testCompile group: 'org.junit.platform', name: 'junit-platform-runner', version: junitPlatformVersion + } + + test { + useJUnitPlatform() + } + + scoverage { + minimumRate = 0.5 + } +} + +scoverage { + minimumRate = 0.5 +} + +project(":2_11").tasks.reportScoverage.mustRunAfter(project(":2_12").tasks.reportScoverage) \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module-cross-version/settings.gradle b/src/functionalTest/resources/projects/scala-multi-module-cross-version/settings.gradle new file mode 100644 index 0000000..6d138e6 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-cross-version/settings.gradle @@ -0,0 +1 @@ +include '2_11', '2_12' \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/a/build.gradle b/src/functionalTest/resources/projects/scala-multi-module/a/build.gradle new file mode 100644 index 0000000..054045f --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/a/build.gradle @@ -0,0 +1,3 @@ +dependencies { + compile project(":common") +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/a/src/main/scala/org/hello/a/WorldA.scala b/src/functionalTest/resources/projects/scala-multi-module/a/src/main/scala/org/hello/a/WorldA.scala new file mode 100644 index 0000000..1d7b2a1 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/a/src/main/scala/org/hello/a/WorldA.scala @@ -0,0 +1,11 @@ +package org.hello.a + +import org.hello.common.WorldCommon + +class WorldA { + + def fooA(): String = { + val s = "a" + new WorldCommon().fooCommon() + s + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/a/src/test/scala/org/hello/a/TestNothingASuite.scala b/src/functionalTest/resources/projects/scala-multi-module/a/src/test/scala/org/hello/a/TestNothingASuite.scala new file mode 100644 index 0000000..996857c --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/a/src/test/scala/org/hello/a/TestNothingASuite.scala @@ -0,0 +1,12 @@ +package org.hello.a + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class TestNothingASuite extends FunSuite { + + test("nothing") { + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/a/src/test/scala/org/hello/a/WorldASuite.scala b/src/functionalTest/resources/projects/scala-multi-module/a/src/test/scala/org/hello/a/WorldASuite.scala new file mode 100644 index 0000000..840bdcc --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/a/src/test/scala/org/hello/a/WorldASuite.scala @@ -0,0 +1,13 @@ +package org.hello.a + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldASuite extends FunSuite { + + test("fooA") { + new WorldA().fooA() + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/b/build.gradle b/src/functionalTest/resources/projects/scala-multi-module/b/build.gradle new file mode 100644 index 0000000..054045f --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/b/build.gradle @@ -0,0 +1,3 @@ +dependencies { + compile project(":common") +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/b/src/main/scala/org/hello/b/WorldB.scala b/src/functionalTest/resources/projects/scala-multi-module/b/src/main/scala/org/hello/b/WorldB.scala new file mode 100644 index 0000000..5c8bb57 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/b/src/main/scala/org/hello/b/WorldB.scala @@ -0,0 +1,11 @@ +package org.hello.b + +import org.hello.common.WorldCommon + +class WorldB { + + def fooB(): String = { + val s = "b" + new WorldCommon().fooCommon() + s + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/b/src/test/scala/org/hello/b/TestNothingBSuite.scala b/src/functionalTest/resources/projects/scala-multi-module/b/src/test/scala/org/hello/b/TestNothingBSuite.scala new file mode 100644 index 0000000..bebfee8 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/b/src/test/scala/org/hello/b/TestNothingBSuite.scala @@ -0,0 +1,12 @@ +package org.hello.b + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class TestNothingBSuite extends FunSuite { + + test("nothing") { + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/b/src/test/scala/org/hello/b/WorldBSuite.scala b/src/functionalTest/resources/projects/scala-multi-module/b/src/test/scala/org/hello/b/WorldBSuite.scala new file mode 100644 index 0000000..fdb8d68 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/b/src/test/scala/org/hello/b/WorldBSuite.scala @@ -0,0 +1,13 @@ +package org.hello.b + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldBSuite extends FunSuite { + + test("fooB") { + new WorldB().fooB() + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/build.gradle b/src/functionalTest/resources/projects/scala-multi-module/build.gradle new file mode 100644 index 0000000..dcfad1a --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/build.gradle @@ -0,0 +1,34 @@ +plugins { + id 'org.scoverage' +} + +allprojects { + repositories { + jcenter() + } +} + +description = 'a multi-module Scala project that builds successfully with 100% coverage' + +allprojects { + + apply plugin: 'java' + apply plugin: 'scala' + + dependencies { + compile group: 'org.scala-lang', name: 'scala-library', version: "${scalaVersionMajor}.${scalaVersionMinor}.${scalaVersionBuild}" + + testRuntime group: 'org.junit.vintage', name: 'junit-vintage-engine', version: junitVersion + testCompile group: 'org.junit.platform', name: 'junit-platform-runner', version: junitPlatformVersion + + testCompile group: 'org.scalatest', name: "scalatest_${scalaVersionMajor}.${scalaVersionMinor}", version: scalatestVersion + } + + test { + useJUnitPlatform() + } + + scoverage { + minimumRate = 0.5 + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/common/src/main/scala/org/hello/common/WorldCommon.scala b/src/functionalTest/resources/projects/scala-multi-module/common/src/main/scala/org/hello/common/WorldCommon.scala new file mode 100644 index 0000000..494ab34 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/common/src/main/scala/org/hello/common/WorldCommon.scala @@ -0,0 +1,9 @@ +package org.hello.common + +class WorldCommon { + + def fooCommon(): String = { + val s = "common" + "a" + s + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/common/src/test/scala/org/hello/common/TestNothingCommonSuite.scala b/src/functionalTest/resources/projects/scala-multi-module/common/src/test/scala/org/hello/common/TestNothingCommonSuite.scala new file mode 100644 index 0000000..970cd6c --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/common/src/test/scala/org/hello/common/TestNothingCommonSuite.scala @@ -0,0 +1,12 @@ +package org.hello.common + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class TestNothingCommonSuite extends FunSuite { + + test("nothing") { + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/common/src/test/scala/org/hello/common/WorldCommonSuite.scala b/src/functionalTest/resources/projects/scala-multi-module/common/src/test/scala/org/hello/common/WorldCommonSuite.scala new file mode 100644 index 0000000..94f8984 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/common/src/test/scala/org/hello/common/WorldCommonSuite.scala @@ -0,0 +1,13 @@ +package org.hello.common + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldCommonSuite extends FunSuite { + + test("fooCommon") { + new WorldCommon().fooCommon() + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/settings.gradle b/src/functionalTest/resources/projects/scala-multi-module/settings.gradle new file mode 100644 index 0000000..6eabe3b --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/settings.gradle @@ -0,0 +1 @@ +include 'a', 'b', 'common' \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/src/main/scala/org/hello/World.scala b/src/functionalTest/resources/projects/scala-multi-module/src/main/scala/org/hello/World.scala new file mode 100644 index 0000000..27dbe28 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/src/main/scala/org/hello/World.scala @@ -0,0 +1,9 @@ +package org.hello + +class World { + + def foo(): String = { + val s = "a" + "b" + s + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/src/test/scala/org/hello/TestNothingSuite.scala b/src/functionalTest/resources/projects/scala-multi-module/src/test/scala/org/hello/TestNothingSuite.scala new file mode 100644 index 0000000..1ac25b5 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/src/test/scala/org/hello/TestNothingSuite.scala @@ -0,0 +1,12 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class TestNothingSuite extends FunSuite { + + test("nothing") { + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-multi-module/src/test/scala/org/hello/WorldSuite.scala b/src/functionalTest/resources/projects/scala-multi-module/src/test/scala/org/hello/WorldSuite.scala new file mode 100644 index 0000000..7281a12 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module/src/test/scala/org/hello/WorldSuite.scala @@ -0,0 +1,13 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldSuite extends FunSuite { + + test("foo") { + new World().foo() + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-single-module-dependency-manager/build.gradle b/src/functionalTest/resources/projects/scala-single-module-dependency-manager/build.gradle new file mode 100644 index 0000000..135d248 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-single-module-dependency-manager/build.gradle @@ -0,0 +1,42 @@ +plugins { + id 'io.spring.dependency-management' version "1.0.4.RELEASE" + id 'org.scoverage' +} + +repositories { + jcenter() +} + +description = 'a single-module Scala project with dependency manager that builds successfully with 100% coverage' + +apply plugin: 'java' +apply plugin: 'scala' + + +dependencyManagement { + dependencies { + dependency group: 'org.scala-lang', name: 'scala-library', version: "${scalaVersionMajor}.${scalaVersionMinor}.${scalaVersionBuild}" + } +} + +dependencies { + compile group: 'org.scala-lang', name: 'scala-library' + + // scala compilation with the dependency management plugin needs this (otherwise compilation will fail) + zinc group: 'com.typesafe.zinc', name: 'zinc', version: '0.3.15' + zinc group: 'org.scala-lang', name: 'scala-library', version: '2.10.5' + + testRuntime group: 'org.junit.vintage', name: 'junit-vintage-engine', version: junitVersion + testCompile group: 'org.junit.platform', name: 'junit-platform-runner', version: junitPlatformVersion + + testCompile group: 'org.scalatest', name: "scalatest_${scalaVersionMajor}.${scalaVersionMinor}", version: scalatestVersion +} + +test { + useJUnitPlatform() +} + +scoverage { + minimumRate = 0.3 +} + diff --git a/src/test/happy day/settings.gradle b/src/functionalTest/resources/projects/scala-single-module-dependency-manager/settings.gradle similarity index 100% rename from src/test/happy day/settings.gradle rename to src/functionalTest/resources/projects/scala-single-module-dependency-manager/settings.gradle diff --git a/src/functionalTest/resources/projects/scala-single-module-dependency-manager/src/main/scala/org/hello/World.scala b/src/functionalTest/resources/projects/scala-single-module-dependency-manager/src/main/scala/org/hello/World.scala new file mode 100644 index 0000000..27dbe28 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-single-module-dependency-manager/src/main/scala/org/hello/World.scala @@ -0,0 +1,9 @@ +package org.hello + +class World { + + def foo(): String = { + val s = "a" + "b" + s + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-single-module-dependency-manager/src/test/scala/org/hello/WorldSuite.scala b/src/functionalTest/resources/projects/scala-single-module-dependency-manager/src/test/scala/org/hello/WorldSuite.scala new file mode 100644 index 0000000..7281a12 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-single-module-dependency-manager/src/test/scala/org/hello/WorldSuite.scala @@ -0,0 +1,13 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldSuite extends FunSuite { + + test("foo") { + new World().foo() + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-single-module/build.gradle b/src/functionalTest/resources/projects/scala-single-module/build.gradle new file mode 100644 index 0000000..6ae71be --- /dev/null +++ b/src/functionalTest/resources/projects/scala-single-module/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'org.scoverage' +} + +repositories { + jcenter() +} + +description = 'a single-module Scala project that builds successfully with 50% coverage' + +apply plugin: 'java' +apply plugin: 'scala' + +dependencies { + compile group: 'org.scala-lang', name: 'scala-library', version: "${scalaVersionMajor}.${scalaVersionMinor}.${scalaVersionBuild}" + + testRuntime group: 'org.junit.vintage', name: 'junit-vintage-engine', version: junitVersion + testCompile group: 'org.junit.platform', name: 'junit-platform-runner', version: junitPlatformVersion + + testCompile group: 'org.scalatest', name: "scalatest_${scalaVersionMajor}.${scalaVersionMinor}", version: scalatestVersion +} + +test { + useJUnitPlatform() +} + +scoverage { + minimumRate = 0.3 +} + +if (hasProperty("excludedFile")) { + scoverage.excludedFiles = [excludedFile] +} diff --git a/src/test/runtime/settings.gradle b/src/functionalTest/resources/projects/scala-single-module/settings.gradle similarity index 100% rename from src/test/runtime/settings.gradle rename to src/functionalTest/resources/projects/scala-single-module/settings.gradle diff --git a/src/functionalTest/resources/projects/scala-single-module/src/main/scala/org/hello/World.scala b/src/functionalTest/resources/projects/scala-single-module/src/main/scala/org/hello/World.scala new file mode 100644 index 0000000..270482f --- /dev/null +++ b/src/functionalTest/resources/projects/scala-single-module/src/main/scala/org/hello/World.scala @@ -0,0 +1,12 @@ +package org.hello + +class World { + + def foo(): String = { + val s = "a" + "b" + s + } + + // not covered by tests + def bar(): String = "y" +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-single-module/src/test/scala/org/hello/TestNothingSuite.scala b/src/functionalTest/resources/projects/scala-single-module/src/test/scala/org/hello/TestNothingSuite.scala new file mode 100644 index 0000000..1ac25b5 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-single-module/src/test/scala/org/hello/TestNothingSuite.scala @@ -0,0 +1,12 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class TestNothingSuite extends FunSuite { + + test("nothing") { + } +} \ No newline at end of file diff --git a/src/functionalTest/resources/projects/scala-single-module/src/test/scala/org/hello/WorldSuite.scala b/src/functionalTest/resources/projects/scala-single-module/src/test/scala/org/hello/WorldSuite.scala new file mode 100644 index 0000000..7281a12 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-single-module/src/test/scala/org/hello/WorldSuite.scala @@ -0,0 +1,13 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldSuite extends FunSuite { + + test("foo") { + new World().foo() + } +} \ No newline at end of file diff --git a/src/main/groovy/org/scoverage/AggregateReportApp.java b/src/main/groovy/org/scoverage/AggregateReportApp.java deleted file mode 100644 index 2bf2f14..0000000 --- a/src/main/groovy/org/scoverage/AggregateReportApp.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.scoverage; - -import scoverage.Coverage; -import scoverage.report.CoverageAggregator; - -import java.io.File; - -public class AggregateReportApp { - - public static void main(String... args) { - File rootDir = new File(args[0]); - File reportDir = new File(args[1]); - Boolean clean = Boolean.parseBoolean(args[2]); - - Boolean coverageOutputCobertura = java.lang.Boolean.valueOf(args[3]); - Boolean coverageOutputXML = java.lang.Boolean.valueOf(args[4]); - Boolean coverageOutputHTML = java.lang.Boolean.valueOf(args[5]); - Boolean coverageDebug = java.lang.Boolean.valueOf(args[6]); - - Coverage coverage = CoverageAggregator.aggregate(rootDir, clean).get(); - - ScoverageWriter.write( - rootDir, - reportDir, - coverage, - coverageOutputCobertura, - coverageOutputXML, - coverageOutputHTML, - coverageDebug - ); - } - -} \ No newline at end of file diff --git a/src/main/groovy/org/scoverage/OverallCheckTask.groovy b/src/main/groovy/org/scoverage/OverallCheckTask.groovy index 356ca6e..e56822a 100644 --- a/src/main/groovy/org/scoverage/OverallCheckTask.groovy +++ b/src/main/groovy/org/scoverage/OverallCheckTask.groovy @@ -2,6 +2,7 @@ package org.scoverage import org.gradle.api.DefaultTask import org.gradle.api.GradleException +import org.gradle.api.provider.Property import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.TaskAction import org.gradle.internal.impldep.com.google.common.annotations.VisibleForTesting @@ -43,22 +44,19 @@ enum CoverageType { class OverallCheckTask extends DefaultTask { /** Type of coverage to check. Available options: Line, Statement and Branch */ - CoverageType coverageType = CoverageType.Statement - double minimumRate = 0.75 + final Property coverageType = project.objects.property(CoverageType) + final Property minimumRate = project.objects.property(BigDecimal) - /** Set if want to change default from 'reportDir' in scoverage extension. */ - File reportDir + final Property reportDir = project.objects.property(File) /** Overwrite to test for a specific locale. */ Locale locale @TaskAction void requireLineCoverage() { - def extension = ScoveragePlugin.extensionIn(project) - NumberFormat nf = NumberFormat.getInstance(locale == null ? Locale.getDefault() : locale) - Exception failure = checkLineCoverage(nf, reportDir == null ? extension.reportDir : reportDir, coverageType, minimumRate) + Exception failure = checkLineCoverage(nf, reportDir.get(), coverageType.get(), minimumRate.get().doubleValue()) if (failure) throw failure } diff --git a/src/main/groovy/org/scoverage/ScoverageAggregate.groovy b/src/main/groovy/org/scoverage/ScoverageAggregate.groovy index 8703d09..4094476 100644 --- a/src/main/groovy/org/scoverage/ScoverageAggregate.groovy +++ b/src/main/groovy/org/scoverage/ScoverageAggregate.groovy @@ -1,32 +1,46 @@ package org.scoverage -import org.gradle.api.tasks.JavaExec - -class ScoverageAggregate extends JavaExec { - - boolean clean = false - File reportDir - - @Override - void exec() { - def extension = ScoveragePlugin.extensionIn(project) - setClasspath(ScoveragePlugin.extensionIn(project).pluginClasspath) - setMain('org.scoverage.AggregateReportApp') - def reportPath = reportDirOrDefault() - setArgs([ - project.projectDir, - reportPath.absolutePath, - clean, - // TODO - consider separate options for `report` and `aggregate` tasks - extension.coverageOutputCobertura, - extension.coverageOutputXML, - extension.coverageOutputHTML, - extension.coverageDebug - ]) - super.exec() - } +import org.gradle.api.DefaultTask +import org.gradle.api.provider.Property +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import scoverage.report.CoverageAggregator + +class ScoverageAggregate extends DefaultTask { + + ScoverageRunner runner + + @OutputDirectory + final Property reportDir = project.objects.property(File) + + final Property deleteReportsOnAggregation = project.objects.property(Boolean) + + // TODO - consider separate options for `report` and `aggregate` tasks + final Property coverageOutputCobertura = project.objects.property(Boolean) + final Property coverageOutputXML = project.objects.property(Boolean) + final Property coverageOutputHTML = project.objects.property(Boolean) + final Property coverageDebug = project.objects.property(Boolean) + + @TaskAction + def aggregate() { + runner.run { + def rootDir = project.projectDir + + def coverage = CoverageAggregator.aggregate(rootDir, deleteReportsOnAggregation.get()) + + reportDir.get().deleteDir() - def reportDirOrDefault() { - return reportDir ? reportDir : new File(project.buildDir, 'scoverage-aggregate') + if (coverage.nonEmpty()) { + new ScoverageWriter(project.logger).write( + rootDir, + reportDir.get(), + coverage.get(), + coverageOutputCobertura.get(), + coverageOutputXML.get(), + coverageOutputHTML.get(), + coverageDebug.get() + ) + } + } } } diff --git a/src/main/groovy/org/scoverage/ScoverageExtension.groovy b/src/main/groovy/org/scoverage/ScoverageExtension.groovy index 7c47d1e..8ee680b 100644 --- a/src/main/groovy/org/scoverage/ScoverageExtension.groovy +++ b/src/main/groovy/org/scoverage/ScoverageExtension.groovy @@ -1,18 +1,10 @@ package org.scoverage -import org.gradle.api.Action -import org.gradle.api.GradleException import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.file.FileCollection import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.scala.ScalaPlugin -import org.gradle.api.tasks.SourceSet -import org.gradle.api.tasks.bundling.Jar -import org.gradle.api.tasks.testing.Test -import org.gradle.util.GFileUtils - -import java.util.concurrent.Callable +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property /** * Defines a new SourceSet for the code to be instrumented. @@ -21,142 +13,84 @@ import java.util.concurrent.Callable */ class ScoverageExtension { + /** Version of scoverage to use for the scalac plugin */ + final Property scoverageVersion + + /** Version of scala to use for the scalac plugin */ + final Property scoverageScalaVersion + /** a directory to write working files to */ - File dataDir + final Property dataDir /** a directory to write final output to */ - File reportDir + final Property reportDir /** sources to highlight */ - File sources + final Property sources /** range positioning for highlighting */ - boolean highlighting = true + final Property highlighting /** regex for each excluded package */ - List excludedPackages = [] + final ListProperty excludedPackages /** regex for each excluded file */ - List excludedFiles = [] - - FileCollection pluginClasspath + final ListProperty excludedFiles /** Options for enabling and disabling output */ - boolean coverageOutputCobertura = true - boolean coverageOutputXML = true - boolean coverageOutputHTML = true - boolean coverageDebug = false + final Property coverageOutputCobertura + final Property coverageOutputXML + final Property coverageOutputHTML + final Property coverageDebug + + final Property deleteReportsOnAggregation + + final Property coverageType + final Property minimumRate ScoverageExtension(Project project) { project.plugins.apply(JavaPlugin.class) project.plugins.apply(ScalaPlugin.class) - project.afterEvaluate(configureRuntimeOptions) - - project.configurations.create(ScoveragePlugin.CONFIGURATION_NAME) { - visible = false - transitive = true - description = 'Scoverage dependencies' - } - - def instrumentedSourceSet = project.sourceSets.create('scoverage') { - def original = project.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME) - - resources.source(original.resources) - scala.source(original.java) - scala.source(original.scala) - - compileClasspath += original.compileClasspath + project.configurations.scoverage - runtimeClasspath = it.output + project.configurations.scoverage + original.runtimeClasspath - } - - def scoverageJar = project.tasks.create('jarScoverage', Jar.class) { - dependsOn('scoverageClasses') - classifier = ScoveragePlugin.CONFIGURATION_NAME - from instrumentedSourceSet.output - } - project.artifacts { - scoverage scoverageJar - } - - project.tasks.create(ScoveragePlugin.TEST_NAME, Test.class) { - conventionMapping.map("classpath", new Callable() { - Object call() throws Exception { - def testSourceSet = project.sourceSets.getByName(SourceSet.TEST_SOURCE_SET_NAME) - return testSourceSet.output + - instrumentedSourceSet.output + - project.configurations.scoverage + - testSourceSet.runtimeClasspath - } - }) - group = 'verification' - } - - project.tasks.create(ScoveragePlugin.REPORT_NAME, ScoverageReport.class) { - dependsOn(project.tasks[ScoveragePlugin.TEST_NAME]) - onlyIf { ScoveragePlugin.extensionIn(project).dataDir.list() } - group = 'verification' - } - - project.tasks.create(ScoveragePlugin.CHECK_NAME, OverallCheckTask.class) { - dependsOn(project.tasks[ScoveragePlugin.REPORT_NAME]) - group = 'verification' - } - - sources = project.projectDir - dataDir = new File(project.buildDir, 'scoverage') - reportDir = new File(project.buildDir, 'reports' + File.separatorChar + 'scoverage') - def classLocation = ScoverageExtension.class.getProtectionDomain().getCodeSource().getLocation() - pluginClasspath = project.files(classLocation.file) + project.configurations.scoverage - } - private Action configureRuntimeOptions = new Action() { - - @Override - void execute(Project t) { - - def extension = ScoveragePlugin.extensionIn(t) - extension.dataDir.mkdirs() - - Configuration configuration = t.configurations[ScoveragePlugin.CONFIGURATION_NAME] - File pluginFile - try { - pluginFile = configuration.filter { it.name.contains('plugin') }.iterator().next() - } catch(NoSuchElementException ignored) { - throw new GradleException("Could not find a plugin jar in configuration '${ScoveragePlugin.CONFIGURATION_NAME}'") - } - - t.tasks[ScoveragePlugin.COMPILE_NAME].configure { - List parameters = ['-Xplugin:' + pluginFile.absolutePath] - List existingParameters = scalaCompileOptions.additionalParameters - if (existingParameters) { - parameters.addAll(existingParameters) - } - parameters.add("-P:scoverage:dataDir:${extension.dataDir.absolutePath}".toString()) - if (extension.excludedPackages) { - parameters.add("-P:scoverage:excludedPackages:${extension.excludedPackages.join(';')}".toString()) - } - if (extension.excludedFiles) { - parameters.add("-P:scoverage:excludedFiles:${extension.excludedFiles.join(';')}".toString()) - } - if (extension.highlighting) { - parameters.add('-Yrangepos') - } - doFirst { - GFileUtils.deleteDirectory(destinationDir) - } - scalaCompileOptions.additionalParameters = parameters - // the compile task creates a store of measured statements - outputs.file(new File(extension.dataDir, 'scoverage.coverage.xml')) - } - t.tasks[ScoveragePlugin.TEST_NAME].outputs.upToDateWhen { extension.dataDir.listFiles(measurementFile) } - t.tasks[ScoveragePlugin.REPORT_NAME].configure { - inputs.dir(extension.dataDir) - outputs.dir(extension.reportDir) - } - } - - FilenameFilter measurementFile = new FilenameFilter() { - @Override - boolean accept(File dir, String name) { - return name.startsWith("scoverage.measurements.") - } - } + scoverageVersion = project.objects.property(String) + scoverageVersion.set('1.3.1') + + scoverageScalaVersion = project.objects.property(String) + scoverageScalaVersion.set('2.12') + + sources = project.objects.property(File) + sources.set(project.projectDir) + + dataDir = project.objects.property(File) + dataDir.set(new File(project.buildDir, 'scoverage')) + + reportDir = project.objects.property(File) + reportDir.set(new File(project.buildDir, ScoveragePlugin.DEFAULT_REPORT_DIR)) + + highlighting = project.objects.property(Boolean) + highlighting.set(true) + + excludedPackages = project.objects.listProperty(String) + excludedPackages.set([]) + + excludedFiles = project.objects.listProperty(String) + excludedFiles.set([]) + + coverageOutputCobertura = project.objects.property(Boolean) + coverageOutputCobertura.set(true) + + coverageOutputXML = project.objects.property(Boolean) + coverageOutputXML.set(true) + + coverageOutputHTML = project.objects.property(Boolean) + coverageOutputHTML.set(true) + + coverageDebug = project.objects.property(Boolean) + coverageDebug.set(false) + + deleteReportsOnAggregation = project.objects.property(Boolean) + deleteReportsOnAggregation.set(false) + + coverageType = project.objects.property(CoverageType) + coverageType.set(CoverageType.Statement) + minimumRate = project.objects.property(BigDecimal) + minimumRate.set(0.75) } } diff --git a/src/main/groovy/org/scoverage/ScoveragePlugin.groovy b/src/main/groovy/org/scoverage/ScoveragePlugin.groovy index 16a87be..7c6ac63 100644 --- a/src/main/groovy/org/scoverage/ScoveragePlugin.groovy +++ b/src/main/groovy/org/scoverage/ScoveragePlugin.groovy @@ -1,24 +1,277 @@ package org.scoverage +import org.apache.commons.io.FileUtils import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.invocation.Gradle +import org.gradle.api.plugins.PluginAware +import org.gradle.api.tasks.SourceSet +import org.gradle.api.tasks.scala.ScalaCompile -class ScoveragePlugin implements Plugin { - static String CONFIGURATION_NAME = 'scoverage' +import java.nio.file.Files - static String TEST_NAME = 'testScoverage' - static String REPORT_NAME = 'reportScoverage' - static String CHECK_NAME = 'checkScoverage' - static String COMPILE_NAME = 'compileScoverageScala' +import static groovy.io.FileType.FILES + +class ScoveragePlugin implements Plugin { + + static final String CONFIGURATION_NAME = 'scoverage' + static final String REPORT_NAME = 'reportScoverage' + static final String CHECK_NAME = 'checkScoverage' + static final String COMPILE_NAME = 'compileScoverageScala' + static final String AGGREGATE_NAME = 'aggregateScoverage' + + static final String DEFAULT_REPORT_DIR = 'reports' + File.separatorChar + 'scoverage' @Override - void apply(Project t) { - if (t.extensions.findByName(CONFIGURATION_NAME) == null) { - t.extensions.create(CONFIGURATION_NAME, ScoverageExtension, t) + void apply(PluginAware pluginAware) { + if (pluginAware instanceof Project) { + applyProject(pluginAware) + if (pluginAware == pluginAware.rootProject) { + pluginAware.subprojects { p -> + p.plugins.apply(ScoveragePlugin) + } + } + } else if (pluginAware instanceof Gradle) { + pluginAware.allprojects { p -> + p.plugins.apply(ScoveragePlugin) + } + } else { + throw new IllegalArgumentException("${pluginAware.getClass()} is currently not supported as an apply target, please report if you need it") } } - protected static ScoverageExtension extensionIn(Project project) { - project.extensions[CONFIGURATION_NAME] as ScoverageExtension + void applyProject(Project project) { + + if (project.plugins.hasPlugin(ScoveragePlugin)) { + project.logger.info("Project ${project.name} already has the scoverage plugin") + return + } + project.logger.info("Applying scoverage plugin to $project.name") + + def extension = project.extensions.create('scoverage', ScoverageExtension, project) + if (!project.configurations.asMap[CONFIGURATION_NAME]) { + project.configurations.create(CONFIGURATION_NAME) { + visible = false + transitive = true + description = 'Scoverage dependencies' + } + + project.afterEvaluate { + def scoverageVersion = project.extensions.scoverage.scoverageVersion.get() + def scalaVersion = null + + def scalaLibrary = project.configurations.compile.dependencies.find { + it.group == "org.scala-lang" && it.name == "scala-library" + } + + if (scalaLibrary != null) { + scalaVersion = scalaLibrary.version + } + + if (scalaVersion == null && project.pluginManager.hasPlugin("io.spring.dependency-management")) { + scalaVersion = project.dependencyManagement.compile.managedVersions["org.scala-lang:scala-library"] + } + + if (scalaVersion == null) { + scalaVersion = project.extensions.scoverage.scoverageScalaVersion.get() + } else { + scalaVersion = scalaVersion.substring(0, scalaVersion.lastIndexOf(".")) + } + + def fullScoverageVersion = "$scalaVersion:$scoverageVersion" + + project.logger.info("Using scoverage scalac plugin version '$fullScoverageVersion'") + + project.dependencies { + scoverage("org.scoverage:scalac-scoverage-plugin_$fullScoverageVersion") + scoverage("org.scoverage:scalac-scoverage-runtime_$fullScoverageVersion") + } + } + } + + createTasks(project, extension) + } + + private void createTasks(Project project, ScoverageExtension extension) { + + ScoverageRunner scoverageRunner = new ScoverageRunner(project.configurations.scoverage) + + def originalSourceSet = project.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME) + def instrumentedSourceSet = project.sourceSets.create('scoverage') { + + resources.source(originalSourceSet.resources) + scala.source(originalSourceSet.scala) + + compileClasspath += originalSourceSet.compileClasspath + project.configurations.scoverage + runtimeClasspath = it.output + project.configurations.scoverage + originalSourceSet.runtimeClasspath + } + + def originalCompileTask = project.tasks[originalSourceSet.getCompileTaskName("scala")] + def originalJarTask = project.tasks[originalSourceSet.getJarTaskName()] + + def compileTask = project.tasks[instrumentedSourceSet.getCompileTaskName("scala")] + compileTask.mustRunAfter(originalCompileTask) + project.test.mustRunAfter(compileTask) + originalJarTask.mustRunAfter(compileTask) + + def reportTask = project.tasks.create(REPORT_NAME, ScoverageReport.class) { + dependsOn compileTask, project.test + onlyIf { extension.dataDir.get().list() } + group = 'verification' + runner = scoverageRunner + reportDir = extension.reportDir + sources = extension.sources + dataDir = extension.dataDir + coverageOutputCobertura = extension.coverageOutputCobertura + coverageOutputXML = extension.coverageOutputXML + coverageOutputHTML = extension.coverageOutputHTML + coverageDebug = extension.coverageDebug + } + + project.tasks.create(CHECK_NAME, OverallCheckTask.class) { + dependsOn(reportTask) + onlyIf { extension.reportDir.get().list() } + group = 'verification' + coverageType = extension.coverageType + minimumRate = extension.minimumRate + reportDir = extension.reportDir + } + + project.afterEvaluate { + + // define aggregation task + if (project.childProjects.size() > 0) { + def reportTasks = project.getAllprojects().collect { it.tasks.withType(ScoverageReport) } + def aggregationTask = project.tasks.create(AGGREGATE_NAME, ScoverageAggregate.class) { + dependsOn(reportTasks) + group = 'verification' + runner = scoverageRunner + reportDir = extension.reportDir + deleteReportsOnAggregation = extension.deleteReportsOnAggregation + coverageOutputCobertura = extension.coverageOutputCobertura + coverageOutputXML = extension.coverageOutputXML + coverageOutputHTML = extension.coverageOutputHTML + coverageDebug = extension.coverageDebug + } + project.tasks[CHECK_NAME].mustRunAfter(aggregationTask) + } + + // make this project's scoverage compilation depend on scoverage compilation of any other project + // which this project depends on its normal compilation + // (essential when running without normal compilation on multi-module projects with inner dependencies) + def originalCompilationDependencies = recursiveDependenciesOf(compileTask).findAll { + it instanceof ScalaCompile + } + originalCompilationDependencies.each { + def dependencyProjectCompileTask = it.project.tasks[COMPILE_NAME] + def dependencyProjectReportTask = it.project.tasks[REPORT_NAME] + if (dependencyProjectCompileTask != null) { + compileTask.dependsOn(dependencyProjectCompileTask) + // we don't want this project's test to affect the other project's report + project.test.mustRunAfter(dependencyProjectReportTask) + } + } + + compileTask.configure { + File pluginFile = project.configurations[CONFIGURATION_NAME].find { + it.name.startsWith("scalac-scoverage-plugin") + } + List parameters = ['-Xplugin:' + pluginFile.absolutePath] + List existingParameters = scalaCompileOptions.additionalParameters + if (existingParameters) { + parameters.addAll(existingParameters) + } + parameters.add("-P:scoverage:dataDir:${extension.dataDir.get().absolutePath}".toString()) + if (extension.excludedPackages.get()) { + def packages = extension.excludedPackages.get().join(';') + parameters.add("-P:scoverage:excludedPackages:$packages".toString()) + } + if (extension.excludedFiles.get()) { + def packages = extension.excludedFiles.get().join(';') + parameters.add("-P:scoverage:excludedFiles:$packages".toString()) + } + if (extension.highlighting.get()) { + parameters.add('-Yrangepos') + } + scalaCompileOptions.additionalParameters = parameters + // the compile task creates a store of measured statements + outputs.file(new File(extension.dataDir.get(), 'scoverage.coverage.xml')) + } + } + + project.gradle.taskGraph.whenReady { graph -> + if (graph.hasTask(reportTask)) { + project.test.configure { + project.logger.debug("Adding instrumented classes to '${path}' classpath") + + classpath = project.configurations.scoverage + instrumentedSourceSet.output + classpath + + outputs.upToDateWhen { + extension.dataDir.get().listFiles(new FilenameFilter() { + @Override + boolean accept(File dir, String name) { + return name.startsWith("scoverage.measurements.") + } + }) + } + } + + compileTask.configure { + if (!graph.hasTask(originalCompileTask)) { + destinationDir = originalCompileTask.destinationDir + } else { + doFirst { + destinationDir.deleteDir() + } + + // delete non-instrumented classes by comparing normally compiled classes to those compiled with scoverage + doLast { + def originalCompileTaskName = project.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME) + .getCompileTaskName("scala") + def originalDestinationDir = project.tasks[originalCompileTaskName].destinationDir + + def findFiles = { File dir, Closure condition = null -> + def files = [] + + if (dir.exists()) { + dir.eachFileRecurse(FILES) { f -> + if (condition == null || condition(f)) { + def relativePath = dir.relativePath(f) + files << relativePath + } + } + } + + return files + } + + def isSameFile = { String relativePath -> + def fileA = new File(originalDestinationDir, relativePath) + def fileB = new File(destinationDir, relativePath) + return FileUtils.contentEquals(fileA, fileB) + } + + def originalClasses = findFiles(originalDestinationDir) + def identicalInstrumentedClasses = findFiles(destinationDir, { f -> + def relativePath = destinationDir.relativePath(f) + return originalClasses.contains(relativePath) && isSameFile(relativePath) + }) + + identicalInstrumentedClasses.each { f -> + Files.deleteIfExists(destinationDir.toPath().resolve(f)) + } + } + } + } + } + } + } + + private Set recursiveDependenciesOf(Task task) { + + def directDependencies = task.getTaskDependencies().getDependencies(task) + def nestedDependencies = directDependencies.collect {recursiveDependenciesOf(it) }.flatten() + return directDependencies + nestedDependencies } -} +} \ No newline at end of file diff --git a/src/main/groovy/org/scoverage/ScoverageReport.groovy b/src/main/groovy/org/scoverage/ScoverageReport.groovy index ddf81ac..ed2d6db 100644 --- a/src/main/groovy/org/scoverage/ScoverageReport.groovy +++ b/src/main/groovy/org/scoverage/ScoverageReport.groovy @@ -1,26 +1,64 @@ package org.scoverage +import org.gradle.api.DefaultTask +import org.gradle.api.provider.Property import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.JavaExec +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import scala.collection.Seq +import scala.collection.Set +import scoverage.Coverage +import scoverage.IOUtils +import scoverage.Serializer @CacheableTask -class ScoverageReport extends JavaExec { - - @Override - void exec() { - def extension = ScoveragePlugin.extensionIn(project) - extension.reportDir.mkdirs() - setClasspath(extension.pluginClasspath) - setMain('org.scoverage.SingleReportApp') - setArgs([ - /* sourceDir = */ extension.sources.absolutePath, - /* dataDir = */ extension.dataDir.absolutePath, - /* reportDir = */ extension.reportDir.absolutePath, - extension.coverageOutputCobertura, - extension.coverageOutputXML, - extension.coverageOutputHTML, - extension.coverageDebug - ]) - super.exec() +class ScoverageReport extends DefaultTask { + + ScoverageRunner runner + + @Input + final Property dataDir = project.objects.property(File) + + @Input + final Property sources = project.objects.property(File) + + @OutputDirectory + final Property reportDir = project.objects.property(File) + + final Property coverageOutputCobertura = project.objects.property(Boolean) + final Property coverageOutputXML = project.objects.property(Boolean) + final Property coverageOutputHTML = project.objects.property(Boolean) + final Property coverageDebug = project.objects.property(Boolean) + + @TaskAction + def report() { + runner.run { + reportDir.get().mkdirs() + + File coverageFile = Serializer.coverageFile(dataDir.get()) + + if (!coverageFile.exists()) { + project.logger.info("[scoverage] Could not find coverage file, skipping...") + } else { + File[] array = IOUtils.findMeasurementFiles(dataDir.get()) + // TODO: patch scoverage core to use a consistent collection type? + Seq measurementFiles = scala.collection.JavaConversions.asScalaBuffer(Arrays.asList(array)) + + Coverage coverage = Serializer.deserialize(coverageFile) + + Set measurements = IOUtils.invoked(measurementFiles) + coverage.apply(measurements) + + new ScoverageWriter(project.logger).write( + sources.get(), + reportDir.get(), + coverage, + coverageOutputCobertura.get(), + coverageOutputXML.get(), + coverageOutputHTML.get(), + coverageDebug.get()) + } + } } } diff --git a/src/main/groovy/org/scoverage/ScoverageRunner.groovy b/src/main/groovy/org/scoverage/ScoverageRunner.groovy new file mode 100644 index 0000000..48889e7 --- /dev/null +++ b/src/main/groovy/org/scoverage/ScoverageRunner.groovy @@ -0,0 +1,32 @@ +package org.scoverage + +import org.gradle.api.file.FileCollection + +import java.lang.reflect.Method + +class ScoverageRunner { + + private FileCollection runtimeClasspath + + ScoverageRunner(FileCollection runtimeClasspath) { + + this.runtimeClasspath = runtimeClasspath + } + + def run(Closure action) { + + URLClassLoader cloader = (URLClassLoader) Thread.currentThread().getContextClassLoader() + + Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class) + method.setAccessible(true) + + runtimeClasspath.files.each { f -> + def url = f.toURL() + if (!cloader.getURLs().contains(url)) { + method.invoke(cloader, url) + } + } + + action.call() + } +} diff --git a/src/main/groovy/org/scoverage/ScoverageWriter.java b/src/main/groovy/org/scoverage/ScoverageWriter.java index 0d8ab2f..cf68851 100644 --- a/src/main/groovy/org/scoverage/ScoverageWriter.java +++ b/src/main/groovy/org/scoverage/ScoverageWriter.java @@ -1,5 +1,6 @@ package org.scoverage; +import org.gradle.api.logging.Logger; import scoverage.Constants; import scoverage.Coverage; import scoverage.report.CoberturaXmlWriter; @@ -15,6 +16,13 @@ */ public class ScoverageWriter { + private final Logger logger; + + public ScoverageWriter(Logger logger) { + + this.logger = logger; + } + /** * Generates all reports from given data. * @@ -26,7 +34,7 @@ public class ScoverageWriter { * @param coverageOutputHTML switch for Scoverage HTML output * @param coverageDebug switch for Scoverage Debug output */ - public static void write(File sourceDir, + public void write(File sourceDir, File reportDir, Coverage coverage, Boolean coverageOutputCobertura, @@ -34,13 +42,13 @@ public static void write(File sourceDir, Boolean coverageOutputHTML, Boolean coverageDebug) { - System.out.println("[scoverage] Generating scoverage reports..."); + logger.info("[scoverage] Generating scoverage reports..."); reportDir.mkdirs(); if (coverageOutputCobertura) { new CoberturaXmlWriter(sourceDir, reportDir).write(coverage); - System.out.println("[scoverage] Written Cobertura XML report to " + + logger.info("[scoverage] Written Cobertura XML report to " + reportDir.getAbsolutePath() + File.separator + "cobertura.xml"); @@ -48,13 +56,13 @@ public static void write(File sourceDir, if (coverageOutputXML) { new ScoverageXmlWriter(sourceDir, reportDir, /* debug = */ false).write(coverage); - System.out.println("[scoverage] Written XML report to " + + logger.info("[scoverage] Written XML report to " + reportDir.getAbsolutePath() + File.separator + Constants.XMLReportFilename()); if (coverageDebug) { new ScoverageXmlWriter(sourceDir, reportDir, /* debug = */ true).write(coverage); - System.out.println("[scoverage] Written XML report with debug information to " + + logger.info("[scoverage] Written XML report with debug information to " + reportDir.getAbsolutePath() + File.separator + Constants.XMLReportFilenameWithDebug()); @@ -63,12 +71,12 @@ public static void write(File sourceDir, if (coverageOutputHTML) { new ScoverageHtmlWriter(sourceDir, reportDir).write(coverage); - System.out.println("[scoverage] Written HTML report to " + + logger.info("[scoverage] Written HTML report to " + reportDir.getAbsolutePath() + File.separator + "index.html"); } - System.out.println("[scoverage] Coverage reports completed"); + logger.info("[scoverage] Coverage reports completed"); } } diff --git a/src/main/groovy/org/scoverage/SingleReportApp.java b/src/main/groovy/org/scoverage/SingleReportApp.java deleted file mode 100644 index 998cb83..0000000 --- a/src/main/groovy/org/scoverage/SingleReportApp.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.scoverage; - -import scala.collection.Seq; -import scala.collection.Set; -import scoverage.Coverage; -import scoverage.IOUtils; -import scoverage.Serializer; - -import java.io.File; -import java.util.Arrays; - -/** - * late binding of scoverage core libraries (without a dependency on groovy) - */ -public class SingleReportApp { - - public static void main(String... args) { - File sourceDir = new File(args[0]); - File dataDir = new File(args[1]); - File reportDir = new File(args[2]); - - Boolean coverageOutputCobertura = java.lang.Boolean.valueOf(args[3]); - Boolean coverageOutputXML = java.lang.Boolean.valueOf(args[4]); - Boolean coverageOutputHTML = java.lang.Boolean.valueOf(args[5]); - Boolean coverageDebug = java.lang.Boolean.valueOf(args[6]); - - File coverageFile = Serializer.coverageFile(dataDir); - - if (!coverageFile.exists()) { - System.out.println("[scoverage] Could not find coverage file, skipping..."); - } else { - File[] array = IOUtils.findMeasurementFiles(dataDir); - // TODO: patch scoverage core to use a consistent collection type? - Seq measurementFiles = scala.collection.JavaConversions.asScalaBuffer(Arrays.asList(array)); - - Coverage coverage = Serializer.deserialize(coverageFile); - - Set measurements = IOUtils.invoked(measurementFiles); - coverage.apply(measurements); - - ScoverageWriter.write( - sourceDir, - reportDir, - coverage, - coverageOutputCobertura, - coverageOutputXML, - coverageOutputHTML, - coverageDebug); - } - } - - -} \ No newline at end of file diff --git a/src/test/groovy/org/scoverage/AcceptanceTestUtils.groovy b/src/test/groovy/org/scoverage/AcceptanceTestUtils.groovy deleted file mode 100644 index 803da60..0000000 --- a/src/test/groovy/org/scoverage/AcceptanceTestUtils.groovy +++ /dev/null @@ -1,49 +0,0 @@ -package org.scoverage - -import org.gradle.tooling.BuildLauncher -import org.gradle.tooling.GradleConnector -import org.hamcrest.core.Is -import org.junit.Assert - -import java.text.NumberFormat - -/** - * Some utils for easy acceptance testing. - */ -class AcceptanceTestUtils { - - XmlParser parser - - AcceptanceTestUtils() { - parser = new XmlParser() - parser.setFeature('http://apache.org/xml/features/disallow-doctype-decl', false) - parser.setFeature('http://apache.org/xml/features/nonvalidating/load-external-dtd', false) - } - - protected BuildLauncher setupBuild(File projectRoot) { - return GradleConnector. - newConnector(). - forProjectDirectory(projectRoot). - connect(). - newBuild(). - withArguments( - '--init-script', - new File(System.properties.getProperty('user.dir'), 'init-scoverage.gradle').toString()) - } - - protected void checkFile(String description, File file, boolean shouldExist) throws Exception { - Assert.assertThat(description + ' should be created at ' + file.absolutePath, file.exists(), Is.is(shouldExist)) - } - - protected File reportDir(File baseDir) { - return new File(baseDir, 'build/reports/scoverage') - } - - protected Double coverage(File reportDir, CoverageType coverageType) { - File reportFile = new File(reportDir, coverageType.fileName) - def xml = parser.parse(reportFile) - println("reportfile path: ${reportFile.absolutePath}") - NumberFormat nf = NumberFormat.getInstance(); - nf.parse(xml.attribute(coverageType.paramName) as String).doubleValue(); - } -} diff --git a/src/test/groovy/org/scoverage/AggregationAcceptanceTest.groovy b/src/test/groovy/org/scoverage/AggregationAcceptanceTest.groovy deleted file mode 100644 index d5883f2..0000000 --- a/src/test/groovy/org/scoverage/AggregationAcceptanceTest.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package org.scoverage - -import org.junit.Test - -class AggregationAcceptanceTest extends AcceptanceTestUtils { - - @Test - public void testMultiProjectAggregation() throws Exception { - File projectDir = new File('src/test/water') - def build = setupBuild(projectDir) - build.forTasks('clean', 'aggregateScoverage').run() - def indexHtml = new File(aggregateReportDir(projectDir), 'index.html') - checkFile('an aggregated index HTML file', indexHtml, true) - def cobertura = new File(aggregateReportDir(projectDir), 'cobertura.xml') - checkFile('an aggregated cobertura XML file', cobertura, true) - def scoverageXml = new File(aggregateReportDir(projectDir), 'scoverage.xml') - checkFile('an aggregated scoverage XML file', scoverageXml, true) - def krillsHtml = new File(aggregateReportDir(projectDir), 'krills.html') - checkFile('a HTML file for \'krills\' sub-project', krillsHtml, true) - def whalesHtml = new File(aggregateReportDir(projectDir), 'whales.html') - checkFile('a HTML file for \'whales\' sub-project', whalesHtml, true) - } - - private static File aggregateReportDir(File baseDir) { - return new File(baseDir, 'build/scoverage-aggregate') - } -} diff --git a/src/test/groovy/org/scoverage/OverallCheckTaskTest.groovy b/src/test/groovy/org/scoverage/OverallCheckTaskTest.groovy index fcc26ab..27c68dc 100644 --- a/src/test/groovy/org/scoverage/OverallCheckTaskTest.groovy +++ b/src/test/groovy/org/scoverage/OverallCheckTaskTest.groovy @@ -4,8 +4,11 @@ import org.gradle.api.GradleException import org.hamcrest.Description import org.hamcrest.Matcher import org.hamcrest.TypeSafeMatcher +import org.junit.Rule import org.junit.Test +import org.junit.rules.TemporaryFolder +import java.nio.file.Paths import java.text.NumberFormat import static org.junit.Assert.assertNull @@ -43,7 +46,10 @@ class OverallCheckTaskTest { private NumberFormat numberFormat = NumberFormat.getInstance(Locale.US) - private static File reportDir = new File('src/test/resources') + private File reportDir = Paths.get(getClass().getClassLoader().getResource("checkTask").toURI()).toFile() + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder() private static Matcher failsWith(String message) { return new CauseMatcher( @@ -57,7 +63,7 @@ class OverallCheckTaskTest { @Test void failsWhenReportFileIsNotFound() { assertThat( - checkLineCoverage(numberFormat, new File('src/test/nothingthere'), CoverageType.Line, 0.0), + checkLineCoverage(numberFormat, tempDir.getRoot(), CoverageType.Line, 0.0), failsWith(OverallCheckTask.fileNotFoundErrorMsg(CoverageType.Line))) } @@ -117,5 +123,4 @@ class OverallCheckTaskTest { void doesNotFailWhenBranchRateIsAboveTarget() { assertNull(checkLineCoverage(numberFormat, reportDir, CoverageType.Branch, 0.45)) } - } diff --git a/src/test/groovy/org/scoverage/SeparateTestsAcceptanceTest.groovy b/src/test/groovy/org/scoverage/SeparateTestsAcceptanceTest.groovy deleted file mode 100644 index 54c7ec2..0000000 --- a/src/test/groovy/org/scoverage/SeparateTestsAcceptanceTest.groovy +++ /dev/null @@ -1,28 +0,0 @@ -package org.scoverage - -import static org.hamcrest.number.IsCloseTo.closeTo -import org.junit.Test - -import static org.junit.Assert.assertThat - -class SeparateTestsAcceptanceTest extends AcceptanceTestUtils { - - @Test - public void testSeparateTestsWithZinc() throws Exception { - File projectDir = new File('src/test/separate-tests') - File subprojectDir = new File(projectDir, 'a') - File testsSubprojectDir = new File(projectDir, 'a-tests') - def build = setupBuild(projectDir) - build.forTasks('clean', 'reportScoverage').run() - def indexHtml = new File(reportDir(subprojectDir), 'index.html') - checkFile('an index HTML file', indexHtml, true) - def testsIndexHtml = new File(reportDir(testsSubprojectDir), 'index.html') - checkFile('an index HTML file', testsIndexHtml, false) - def helloHtml = new File(reportDir(subprojectDir), 'src/main/scala/hello/Hello.scala.html') - checkFile('Hello.scala html file', helloHtml, true) - def branchCoverage = coverage(reportDir(subprojectDir), CoverageType.Branch) - def statementCoverage = coverage(reportDir(subprojectDir), CoverageType.Statement) - assertThat('Branch coverage should be 100%, was ' + branchCoverage, branchCoverage, closeTo(100.0, 1.0)) - assertThat('Statement coverage should be 100%, was ' + statementCoverage, statementCoverage, closeTo(100.0, 1.0)) - } -} diff --git a/src/test/groovy/org/scoverage/SimpleReportAcceptanceTest.groovy b/src/test/groovy/org/scoverage/SimpleReportAcceptanceTest.groovy deleted file mode 100644 index 8be41e5..0000000 --- a/src/test/groovy/org/scoverage/SimpleReportAcceptanceTest.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package org.scoverage - -import org.junit.Test - -class SimpleReportAcceptanceTest extends AcceptanceTestUtils { - - - @Test - public void testProjectWithCompleteCoverage() throws Exception { - File projectRoot = new File('src/test/happy day') - def build = setupBuild(projectRoot) - build.forTasks('clean', 'checkScoverage').run() - def html = new File(reportDir(projectRoot), 'index.html') - checkFile('an index HTML file', html, true) - def cobertura = new File(reportDir(projectRoot), 'cobertura.xml') - checkFile('a cobertura XML file', cobertura, true) - def scoverageXml = new File(reportDir(projectRoot), 'scoverage.xml') - checkFile('a scoverage XML file', scoverageXml, true) - } - - @Test - public void testRun() throws Exception { - File projectRoot = new File('src/test/runtime') - def build = setupBuild(projectRoot) - build.forTasks('clean', 'run').run() - } -} diff --git a/src/test/happy day/build.gradle b/src/test/happy day/build.gradle deleted file mode 100644 index a4a19ef..0000000 --- a/src/test/happy day/build.gradle +++ /dev/null @@ -1,28 +0,0 @@ -description = 'a project that builds successfully with 100% coverage' - -buildscript { - repositories { - // need to get up to the working directory of gradle-plugins build - flatDir dir: "${project.projectDir}/../../../build/libs" - } - dependencies { - classpath name: 'gradle-scoverage', version: '+' - } -} - -apply plugin: 'org.scoverage' - -repositories { - mavenCentral() -} - -dependencies { - scoverage scoverageLib - compile 'org.scala-lang:scala-library:2.11.0' - testCompile 'junit:junit:4.11' -} - -checkScoverage { - minimumRate = 1.0 - coverageType = 'Line' -} \ No newline at end of file diff --git a/src/test/happy day/src/main/java/old/World.java b/src/test/happy day/src/main/java/old/World.java deleted file mode 100644 index 97f710f..0000000 --- a/src/test/happy day/src/main/java/old/World.java +++ /dev/null @@ -1,7 +0,0 @@ -package old; - -public class World { - public String getMessage() { - return "Hello old boy"; - } -} \ No newline at end of file diff --git a/src/test/happy day/src/main/resources/main.txt b/src/test/happy day/src/main/resources/main.txt deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/happy day/src/main/scala/hello/World.scala b/src/test/happy day/src/main/scala/hello/World.scala deleted file mode 100644 index cd1117d..0000000 --- a/src/test/happy day/src/main/scala/hello/World.scala +++ /dev/null @@ -1,8 +0,0 @@ -package hello - -object World { - def say() = { - println(new old.World().getMessage()) - println("ahoy") - } -} \ No newline at end of file diff --git a/src/test/happy day/src/test/resources/test.txt b/src/test/happy day/src/test/resources/test.txt deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/happy day/src/test/scala/hello/ResourcesTest.scala b/src/test/happy day/src/test/scala/hello/ResourcesTest.scala deleted file mode 100644 index fd5573b..0000000 --- a/src/test/happy day/src/test/scala/hello/ResourcesTest.scala +++ /dev/null @@ -1,14 +0,0 @@ -package hello - -import org.junit.Test - -class ResourcesTest { - @Test - def mainResourcesAreBuilt() { - assert(getClass.getResource("/main.txt") != null) - } - @Test - def testResourcesAreBuilt() { - assert(getClass.getResource("/test.txt") != null) - } -} \ No newline at end of file diff --git a/src/test/happy day/src/test/scala/hello/WorldTest.scala b/src/test/happy day/src/test/scala/hello/WorldTest.scala deleted file mode 100644 index a087efa..0000000 --- a/src/test/happy day/src/test/scala/hello/WorldTest.scala +++ /dev/null @@ -1,10 +0,0 @@ -package hello - -import org.junit.Test - -class WorldTest { - @Test - def bob() { - World.say() - } -} \ No newline at end of file diff --git a/src/test/resources/cobertura.xml b/src/test/resources/checkTask/cobertura.xml similarity index 100% rename from src/test/resources/cobertura.xml rename to src/test/resources/checkTask/cobertura.xml diff --git a/src/test/resources/scoverage.xml b/src/test/resources/checkTask/scoverage.xml similarity index 100% rename from src/test/resources/scoverage.xml rename to src/test/resources/checkTask/scoverage.xml diff --git a/src/test/runtime/build.gradle b/src/test/runtime/build.gradle deleted file mode 100644 index 0ed527f..0000000 --- a/src/test/runtime/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -description = 'a project that runs an application and captures scoverage' - -buildscript { - repositories { - // need to get up to the working directory of gradle-plugins build - flatDir dir: "${project.projectDir}/../../../build/libs" - } - dependencies { - classpath name: 'gradle-scoverage', version: '+' - } -} - -apply plugin: 'org.scoverage' - -repositories { - mavenCentral() -} - -dependencies { - scoverage scoverageLib - compile 'org.scala-lang:scala-library:2.11.0' -} - -task run(type: JavaExec) { - classpath = sourceSets.scoverage.runtimeClasspath - main = 'hello.World' -} - -checkScoverage.dependsOn(run) \ No newline at end of file diff --git a/src/test/runtime/src/main/scala/hello/World.scala b/src/test/runtime/src/main/scala/hello/World.scala deleted file mode 100644 index d90e2c9..0000000 --- a/src/test/runtime/src/main/scala/hello/World.scala +++ /dev/null @@ -1,5 +0,0 @@ -package hello - -object World extends App { - println("ahoy") -} \ No newline at end of file diff --git a/src/test/separate-tests/a-tests/src/main/scala/hello/BaseTest.scala b/src/test/separate-tests/a-tests/src/main/scala/hello/BaseTest.scala deleted file mode 100644 index 12d82ae..0000000 --- a/src/test/separate-tests/a-tests/src/main/scala/hello/BaseTest.scala +++ /dev/null @@ -1,7 +0,0 @@ -package hello - -class BaseTest { - def beforeTest() = { - println("Running test!") - } -} \ No newline at end of file diff --git a/src/test/separate-tests/a-tests/src/test/scala/hello/HelloTest.scala b/src/test/separate-tests/a-tests/src/test/scala/hello/HelloTest.scala deleted file mode 100644 index 1c7df23..0000000 --- a/src/test/separate-tests/a-tests/src/test/scala/hello/HelloTest.scala +++ /dev/null @@ -1,13 +0,0 @@ -package hello - -import org.junit.Test -import org.junit.Assert.assertEquals - -class HelloTest extends BaseTest { - - @Test def testText() { - beforeTest() - assertEquals("Hello World", new Hello().text) - } - -} diff --git a/src/test/separate-tests/a/src/main/scala/hello/Hello.scala b/src/test/separate-tests/a/src/main/scala/hello/Hello.scala deleted file mode 100644 index eabfc20..0000000 --- a/src/test/separate-tests/a/src/main/scala/hello/Hello.scala +++ /dev/null @@ -1,5 +0,0 @@ -package hello - -class Hello { - def text = "Hello World" -} diff --git a/src/test/separate-tests/build.gradle b/src/test/separate-tests/build.gradle deleted file mode 100644 index 8a258dd..0000000 --- a/src/test/separate-tests/build.gradle +++ /dev/null @@ -1,63 +0,0 @@ -description = 'a multi-project with separate tests setup for gradle-scoverage' - -buildscript { - repositories { - // need to get up to the working directory of gradle-plugins build - flatDir dir: "${project.projectDir}/../../../build/libs" - } - dependencies { - classpath name: 'gradle-scoverage', version: '+' - } -} - -subprojects { - - repositories { - mavenCentral() - } - - apply plugin: 'scala' - apply plugin: 'org.scoverage' - - dependencies { - compile 'org.scala-lang:scala-library:2.11.4' - scoverage scoverageLib - - testCompile 'junit:junit:4.11' - } - - testScoverage { - onlyIf { project.name.endsWith('-tests') } - } - - reportScoverage { - onlyIf { project.name.endsWith('-tests') } - } - - checkScoverage { - onlyIf { project.name.endsWith('-tests') } - } - -} - -configure(subprojects.findAll { it.name.endsWith('-tests') }) { - def mainProject = project(":${project.name.minus('-tests')}") - dependencies { - testCompile mainProject - scoverage mainProject.configurations.scoverage.artifacts.files - } - scoverage { - sources = mainProject.extensions.scoverage.sources - dataDir = mainProject.extensions.scoverage.dataDir - reportDir = mainProject.extensions.scoverage.reportDir - } - sourceSets { - testScoverage { - compileClasspath += sourceSets.main.output - runtimeClasspath += sourceSets.main.output - } - } - compileScoverageScala { - onlyIf { false } - } -} \ No newline at end of file diff --git a/src/test/separate-tests/settings.gradle b/src/test/separate-tests/settings.gradle deleted file mode 100644 index 85eeb66..0000000 --- a/src/test/separate-tests/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':a', ':a-tests' diff --git a/src/test/water/bluewhale/src/main/scala/whales/BlueWhale.scala b/src/test/water/bluewhale/src/main/scala/whales/BlueWhale.scala deleted file mode 100644 index 2953e26..0000000 --- a/src/test/water/bluewhale/src/main/scala/whales/BlueWhale.scala +++ /dev/null @@ -1,5 +0,0 @@ -package whales - -class BlueWhale { - def swim(): String = "I'm swimming!" -} \ No newline at end of file diff --git a/src/test/water/bluewhale/src/test/scala/whales/BlueWhaleTest.scala b/src/test/water/bluewhale/src/test/scala/whales/BlueWhaleTest.scala deleted file mode 100644 index 2e3d0be..0000000 --- a/src/test/water/bluewhale/src/test/scala/whales/BlueWhaleTest.scala +++ /dev/null @@ -1,11 +0,0 @@ -package whales - -import org.junit.Test -import org.junit.Assert - -class BlueWhaleTest { - - @Test def bob(): Unit = { - Assert.assertEquals("Whale cannot swim :(", new BlueWhale().swim(), "I'm swimming!") - } -} \ No newline at end of file diff --git a/src/test/water/build.gradle b/src/test/water/build.gradle deleted file mode 100644 index a878fe5..0000000 --- a/src/test/water/build.gradle +++ /dev/null @@ -1,33 +0,0 @@ -description = 'a multi-project setup for gradle-scoverage' - -buildscript { - repositories { - // need to get up to the working directory of gradle-plugins build - flatDir dir: "${project.projectDir}/../../../build/libs" - } - dependencies { - classpath name: 'gradle-scoverage', version: '+' - } -} - -allprojects { - repositories { - mavenCentral() - } - - apply plugin: 'org.scoverage' - - dependencies { - scoverage scoverageLib - compile 'org.scala-lang:scala-library:2.11.5' - - testCompile 'junit:junit:4.11' - } -} - -task aggregateScoverage(type: org.scoverage.ScoverageAggregate) - -subprojects { - aggregateScoverage.dependsOn(it.tasks.reportScoverage) -} - diff --git a/src/test/water/krill/src/main/scala/krills/NorthernKrill.scala b/src/test/water/krill/src/main/scala/krills/NorthernKrill.scala deleted file mode 100644 index 16fdf22..0000000 --- a/src/test/water/krill/src/main/scala/krills/NorthernKrill.scala +++ /dev/null @@ -1,5 +0,0 @@ -package krills - -class NorthernKrill { - def swim(): String = "I can only float :(" -} \ No newline at end of file diff --git a/src/test/water/krill/src/test/scala/krills/NorthernKrillTest.scala b/src/test/water/krill/src/test/scala/krills/NorthernKrillTest.scala deleted file mode 100644 index bcb4dd7..0000000 --- a/src/test/water/krill/src/test/scala/krills/NorthernKrillTest.scala +++ /dev/null @@ -1,11 +0,0 @@ -package krills - -import org.junit.Test -import org.junit.Assert - -class NorthernKrillTest { - - @Test def bob(): Unit = { - Assert.assertEquals("Krill can swim", new NorthernKrill().swim(), "I can only float :(") - } -} \ No newline at end of file diff --git a/src/test/water/settings.gradle b/src/test/water/settings.gradle deleted file mode 100644 index a978eb9..0000000 --- a/src/test/water/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include 'bluewhale', 'krill' \ No newline at end of file