Skip to content

Commit ad39e96

Browse files
committed
Allow running scoverage without running the normal compilation (only scoverage compilation)
1 parent 0a6ec0b commit ad39e96

File tree

5 files changed

+99
-47
lines changed

5 files changed

+99
-47
lines changed

src/functionalTest/java/org.scoverage/ScalaSingleModuleTest.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public void checkScoverage() throws Exception {
6161
result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME());
6262

6363
assertReportFilesExist();
64-
assertCoverage(100.0);
64+
assertCoverage(50.0);
6565
}
6666

6767
@Test
@@ -94,6 +94,42 @@ public void reportScoverageWithExcludedClasses() throws Exception {
9494
Assert.assertFalse(resolve(reportDir(), "src/main/scala/org/hello/World.scala.html").exists());
9595
assertCoverage(100.0); // coverage is 100 since no classes are covered
9696

97+
// compiled class should exist in the default classes directory, but not in scoverage
98+
Assert.assertTrue(resolve(buildDir(), "classes/scala/main/org/hello/World.class").exists());
99+
Assert.assertFalse(resolve(buildDir(), "classes/scala/scoverage/org/hello/World.class").exists());
100+
}
101+
102+
@Test
103+
public void reportScoverageWithoutNormalCompilation() throws Exception {
104+
105+
AssertableBuildResult result = run("clean", ScoveragePlugin.getREPORT_NAME(),
106+
"-PrunNormalCompilation=false");
107+
108+
result.assertTaskSkipped("compileScala");
109+
result.assertTaskSucceeded(ScoveragePlugin.getCOMPILE_NAME());
110+
result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME());
111+
result.assertTaskDoesntExist(ScoveragePlugin.getCHECK_NAME());
112+
result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME());
113+
114+
assertReportFilesExist();
115+
assertCoverage(50.0);
116+
117+
Assert.assertTrue(resolve(buildDir(), "classes/scala/main/org/hello/World.class").exists());
118+
Assert.assertFalse(resolve(buildDir(), "classes/scala/scoverage/org/hello/World.class").exists());
119+
}
120+
121+
@Test
122+
public void reportScoverageWithoutNormalCompilationAndWithExcludedClasses() throws Exception {
123+
124+
AssertableBuildResult result = run("clean", ScoveragePlugin.getREPORT_NAME(),
125+
"-PrunNormalCompilation=false", "-PexcludedFile=.*");
126+
127+
Assert.assertTrue(resolve(reportDir(), "index.html").exists());
128+
Assert.assertFalse(resolve(reportDir(), "src/main/scala/org/hello/World.scala.html").exists());
129+
assertCoverage(100.0); // coverage is 100 since no classes are covered
130+
131+
// compiled class should exist in the default classes directory, but not in scoverage
132+
Assert.assertTrue(resolve(buildDir(), "classes/scala/main/org/hello/World.class").exists());
97133
Assert.assertFalse(resolve(buildDir(), "classes/scala/scoverage/org/hello/World.class").exists());
98134
}
99135

src/functionalTest/resources/projects/scala-single-module/build.gradle

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ test {
2525
}
2626

2727
checkScoverage {
28-
minimumRate = 0.5
28+
minimumRate = 0.3
2929
}
3030

3131
if (hasProperty("excludedFile")) {
32-
scoverage {
33-
excludedFiles = [excludedFile]
34-
}
35-
}
32+
scoverage.excludedFiles = [excludedFile]
33+
}
34+
if (hasProperty("runNormalCompilation")) {
35+
scoverage.runNormalCompilation = Boolean.valueOf(runNormalCompilation)
36+
}
37+

src/functionalTest/resources/projects/scala-single-module/src/main/scala/org/hello/World.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@ class World {
66
val s = "a" + "b"
77
s
88
}
9+
10+
// not covered by tests
11+
def bar(): String = "y"
912
}

src/main/groovy/org/scoverage/ScoverageExtension.groovy

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ class ScoverageExtension {
4040

4141
final Property<Boolean> deleteReportsOnAggregation
4242

43+
final Property<Boolean> runNormalCompilation
44+
4345
ScoverageExtension(Project project) {
4446

4547
project.plugins.apply(JavaPlugin.class)
@@ -83,5 +85,8 @@ class ScoverageExtension {
8385

8486
deleteReportsOnAggregation = project.objects.property(Boolean)
8587
deleteReportsOnAggregation.set(false)
88+
89+
runNormalCompilation = project.objects.property(Boolean)
90+
runNormalCompilation.set(true)
8691
}
8792
}

src/main/groovy/org/scoverage/ScoveragePlugin.groovy

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import org.gradle.api.Project
66
import org.gradle.api.invocation.Gradle
77
import org.gradle.api.plugins.PluginAware
88
import org.gradle.api.tasks.SourceSet
9-
import org.gradle.api.tasks.bundling.Jar
109

1110
import java.nio.file.Files
1211

@@ -97,19 +96,13 @@ class ScoveragePlugin implements Plugin<PluginAware> {
9796
runtimeClasspath = it.output + project.configurations.scoverage + originalSourceSet.runtimeClasspath
9897
}
9998

99+
def originalCompileTask = project.tasks[originalSourceSet.getCompileTaskName("scala")]
100+
originalCompileTask.onlyIf { extension.runNormalCompilation.get() }
101+
100102
def compileTask = project.tasks[instrumentedSourceSet.getCompileTaskName("scala")]
101-
compileTask.mustRunAfter(originalSourceSet.getCompileTaskName("scala"))
103+
compileTask.mustRunAfter(originalCompileTask)
102104
project.test.mustRunAfter(compileTask)
103105

104-
def scoverageJar = project.tasks.create('jarScoverage', Jar.class) {
105-
dependsOn(instrumentedSourceSet.classesTaskName)
106-
classifier = CONFIGURATION_NAME
107-
from instrumentedSourceSet.output
108-
}
109-
project.artifacts {
110-
scoverage scoverageJar
111-
}
112-
113106
def reportTask = project.tasks.create(REPORT_NAME, ScoverageReport.class) {
114107
dependsOn compileTask, project.test
115108
onlyIf { extension.dataDir.get().list() }
@@ -146,6 +139,12 @@ class ScoveragePlugin implements Plugin<PluginAware> {
146139
})
147140
}
148141
}
142+
143+
if (!extension.runNormalCompilation.get()) {
144+
project.sourceSets.getByName(SourceSet.TEST_SOURCE_SET_NAME) {
145+
compileClasspath = instrumentedSourceSet.output + compileClasspath
146+
}
147+
}
149148
}
150149
}
151150

@@ -168,8 +167,12 @@ class ScoveragePlugin implements Plugin<PluginAware> {
168167
}
169168

170169
compileTask.configure {
171-
doFirst {
172-
destinationDir.deleteDir()
170+
if (extension.runNormalCompilation.get()) {
171+
doFirst {
172+
destinationDir.deleteDir()
173+
}
174+
} else {
175+
destinationDir = originalCompileTask.destinationDir
173176
}
174177

175178
File pluginFile = project.configurations[CONFIGURATION_NAME].find {
@@ -196,40 +199,43 @@ class ScoveragePlugin implements Plugin<PluginAware> {
196199
// the compile task creates a store of measured statements
197200
outputs.file(new File(extension.dataDir.get(), 'scoverage.coverage.xml'))
198201

199-
doLast {
200-
def originalCompileTaskName = project.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME)
201-
.getCompileTaskName("scala")
202-
def originalDestinationDir = project.tasks[originalCompileTaskName].destinationDir
203-
204-
def findFiles = { File dir, Closure<Boolean> condition = null ->
205-
def files = []
206-
207-
if (dir.exists()) {
208-
dir.eachFileRecurse(FILES) { f ->
209-
if (condition == null || condition(f)) {
210-
def relativePath = dir.relativePath(f)
211-
files << relativePath
202+
if (extension.runNormalCompilation.get()) {
203+
// delete non-instrumented classes by comparing normally compiled classes to those compiled with scoverage
204+
doLast {
205+
def originalCompileTaskName = project.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME)
206+
.getCompileTaskName("scala")
207+
def originalDestinationDir = project.tasks[originalCompileTaskName].destinationDir
208+
209+
def findFiles = { File dir, Closure<Boolean> condition = null ->
210+
def files = []
211+
212+
if (dir.exists()) {
213+
dir.eachFileRecurse(FILES) { f ->
214+
if (condition == null || condition(f)) {
215+
def relativePath = dir.relativePath(f)
216+
files << relativePath
217+
}
212218
}
213219
}
214-
}
215220

216-
return files
217-
}
221+
return files
222+
}
218223

219-
def isSameFile = { String relativePath ->
220-
def fileA = new File(originalDestinationDir, relativePath)
221-
def fileB = new File(destinationDir, relativePath)
222-
return FileUtils.contentEquals(fileA, fileB)
223-
}
224+
def isSameFile = { String relativePath ->
225+
def fileA = new File(originalDestinationDir, relativePath)
226+
def fileB = new File(destinationDir, relativePath)
227+
return FileUtils.contentEquals(fileA, fileB)
228+
}
224229

225-
def originalClasses = findFiles(originalDestinationDir)
226-
def identicalInstrumentedClasses = findFiles(destinationDir, { f ->
227-
def relativePath = destinationDir.relativePath(f)
228-
return originalClasses.contains(relativePath) && isSameFile(relativePath)
229-
})
230+
def originalClasses = findFiles(originalDestinationDir)
231+
def identicalInstrumentedClasses = findFiles(destinationDir, { f ->
232+
def relativePath = destinationDir.relativePath(f)
233+
return originalClasses.contains(relativePath) && isSameFile(relativePath)
234+
})
230235

231-
identicalInstrumentedClasses.each { f ->
232-
Files.deleteIfExists(destinationDir.toPath().resolve(f))
236+
identicalInstrumentedClasses.each { f ->
237+
Files.deleteIfExists(destinationDir.toPath().resolve(f))
238+
}
233239
}
234240
}
235241
}

0 commit comments

Comments
 (0)