Make Scoverage "test" task cacheable and fix aggregated module scoverage report. #202
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hi,
I have discovered that "test" task (when running scoverage) could not be cached in gradle build cache. This is a big problem for me and I cannot use this plugin without this feature.
In order to make this task cacheable, I needed to correctly handle additional outputs (workDir). Unfortunately, it is difficult:
compile
task produces filedataDir/scoverage.coverage
with metadata.test
task produces filesdataDir/scoverage.measurements.*
with measurement data (basically a list of statements ids).The fact that both tasks write to the same directory (it cannot be changed) makes it difficult to correctly describe task outputs. I tried using
fileTree().matching()
, but this cannot be cached (there is an open issue in gradle for that: gradle/gradle#9131). Thus, a complex workaround is needed :(Solution:
dataDir/scoverage.coverage
as an output. It is cached.scoverageSyncMetaWithOutputs
.This could be simplified: Step (3) may be replaced by different report generation than
CoverageAggregator.aggregate
, which assumes that metadata and measurements are located in the same directory.This solves the caching problems and my test build is dramatically faster when rebuilding - as expected. However, some tests in this repository started failing. I discovered that current report generation for multiple test tasks is incorrect.
The problem lies in the method
CoverageAggregator.aggregate
. It can only be used to merge disjointed scoverage data. By "disjointed" I mean reports for different modules (separate compilation units). It cannot be used to merge reports from multiple "test" tasks in a single module.To understand why, check its implementation. When merging, statements ids are are converted in order to make them unique. However, when scoverage.coverage files are the same, statements are supposed to overlap. That is expected because sources are the same.
I solved this problem by changing globalReportTask. Instead of collecting all dataDirs from a single module, it uses a single file that is populated by measurement files from all test tasks in that module.
Lessons learned and ideas:
Known(expected?) problems:
Test tasks share the same workdir, which may cause problems when running them in parallel. Improving
scoverage-scalac-plugin
should solve this issue, but right know user must enforce some ordering between those tasks.