Skip to content

Commit c9be72a

Browse files
Implemented aggregate reports
Resolves #20, #43 Co-authored-by: Leonid Startsev <[email protected]>
1 parent 9d00eeb commit c9be72a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1273
-514
lines changed

README.md

+115-36
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ Minimal supported `Gradle` version: `6.4`.
1010
## Table of content
1111
- [Features](#features)
1212
- [Quickstart](#quickstart)
13-
- [Apply plugin to single-module project](#apply-plugin-to-single-module-project)
13+
- [Apply plugin to a single-module build](#apply-plugin-to-a-single-module-build)
1414
- [Applying plugins with the plugins DSL](#applying-plugins-with-the-plugins-dsl)
1515
- [Legacy Plugin Application: applying plugins with the buildscript block](#legacy-plugin-application-applying-plugins-with-the-buildscript-block)
16-
- [Apply plugin to multi-module project](#apply-plugin-to-multi-module-project)
16+
- [Apply plugin to a multi-module build](#apply-plugin-to-a-multi-module-build)
1717
- [Configuration](#configuration)
1818
- [Configuring JVM test task](#configuring-jvm-test-task)
19-
- [Configuring reports](#configuring-reports)
20-
- [Configuring reports collecting](#configuring-reports-collecting)
19+
- [Configuring aggregated reports](#configuring-aggregated-reports)
20+
- [Configuring module reports](#configuring-module-reports)
2121
- [Configuring entire plugin](#configuring-entire-plugin)
2222
- [Verification](#verification)
2323
- [Tasks](#tasks)
@@ -32,7 +32,7 @@ Minimal supported `Gradle` version: `6.4`.
3232
* Customizable filters for instrumented classes
3333

3434
## Quickstart
35-
### Apply plugin to single-module project
35+
### Apply plugin to a single-module build
3636
#### Applying plugins with the plugins DSL
3737
In top level build file
3838

@@ -94,12 +94,9 @@ apply plugin: 'kover'
9494
```
9595
</details>
9696

97-
### Apply plugin to multi-module project
98-
To apply the plugin to all modules in the project, you need to apply the plugin only to the root module, as shown [above](#apply-plugin-to-single-module-project).
99-
100-
**There are no dependencies between tasks from different modules, they are executed independently.**
101-
102-
**Cross-module tests are not supported in reports and validation yet. For each test, only the classpath belonging to the current module is taken.**
97+
### Apply plugin to a multi-module build
98+
To apply the plugin to all Gradle modules, you just need to apply the plugin only to the root module, as shown [above](#apply-plugin-to-a-single-module-build).
99+
Applying the plugin to submodules if you have already applied it to the root module will cause configuration error.
103100

104101
## Configuration
105102

@@ -194,21 +191,24 @@ android {
194191
</details>
195192

196193

197-
### Configuring reports
198-
If you need to change the name of the XML report file or HTML directory, you may configure the corresponding tasks
194+
### Configuring aggregated reports
195+
Aggregated report provides report using combined classpath and coverage stats from the module in which plugin is applied and all its submodules.
196+
197+
If you need to change the name of the XML report file or HTML directory, you may configure the corresponding tasks in
198+
the module in which the plugin is applied (usually this is the root module).
199199

200200
<details open>
201201
<summary>Kotlin</summary>
202202

203203
```kotlin
204204
tasks.koverHtmlReport {
205205
isEnabled = true // false to disable report generation
206-
htmlReportDir.set(layout.buildDirectory.dir("my-reports/html-result"))
206+
htmlReportDir.set(layout.buildDirectory.dir("my-agg-report/html-result"))
207207
}
208208

209209
tasks.koverXmlReport {
210210
isEnabled = true // false to disable report generation
211-
xmlReportFile.set(layout.buildDirectory.file("my-reports/result.xml"))
211+
xmlReportFile.set(layout.buildDirectory.file("my-agg-report/result.xml"))
212212
}
213213
```
214214
</details>
@@ -229,15 +229,23 @@ tasks.koverXmlReport {
229229
```
230230
</details>
231231

232-
### Configuring reports collecting
233-
You may specify custom directory to collect reports from all modules in the build file of the root module:
232+
### Configuring module reports
233+
If you need to change the name of the XML report file or HTML directory for a specific module, you may configure
234+
the corresponding tasks in this module.
235+
234236

235237
<details open>
236238
<summary>Kotlin</summary>
237239

238240
```kotlin
239-
tasks.koverCollectReports {
240-
outputDir.set(layout.buildDirectory.dir("my-reports-dir") )
241+
tasks.koverHtmlModuleReport {
242+
isEnabled = true // false to disable report generation
243+
htmlReportDir.set(layout.buildDirectory.dir("my-module-report/html-result"))
244+
}
245+
246+
tasks.koverXmlModuleReport {
247+
isEnabled = true // false to disable report generation
248+
xmlReportFile.set(layout.buildDirectory.file("my-module-report/result.xml"))
241249
}
242250
```
243251
</details>
@@ -246,8 +254,38 @@ tasks.koverCollectReports {
246254
<summary>Groovy</summary>
247255

248256
```groovy
249-
tasks.koverCollectReports {
250-
outputDir.set(layout.buildDirectory.dir("my-reports-dir") )
257+
tasks.koverHtmlModuleReport {
258+
enabled = true // false to disable report generation
259+
htmlReportDir.set(layout.buildDirectory.dir("my-module-report/html-result"))
260+
}
261+
262+
tasks.koverXmlModuleReport {
263+
enabled = true // false to disable report generation
264+
xmlReportFile.set(layout.buildDirectory.file("my-module-report/result.xml"))
265+
}
266+
```
267+
</details>
268+
269+
You may collect all modules reports into one directory using `koverCollectModuleReports` task.
270+
Also, you may specify custom directory to collect modules reports in the build file of the module in which the plugin
271+
is applied (usually this is the root module):
272+
273+
<details open>
274+
<summary>Kotlin</summary>
275+
276+
```kotlin
277+
tasks.koverCollectModuleReports {
278+
outputDir.set(layout.buildDirectory.dir("all-modules-reports") )
279+
}
280+
```
281+
</details>
282+
283+
<details>
284+
<summary>Groovy</summary>
285+
286+
```groovy
287+
tasks.koverCollectModuleReports {
288+
outputDir.set(layout.buildDirectory.dir("all-modules-reports") )
251289
}
252290
```
253291
</details>
@@ -284,23 +322,25 @@ kover {
284322
</details>
285323

286324
## Verification
287-
For all test task of module, you can specify one or more rules that check the values of the code coverage counters.
325+
You may specify one or more rules that check the values of the code coverage counters.
288326

289327
Validation rules work for both types of agents.
290328

291329
*The plugin currently only supports line counter values.*
292330

293-
In the build file of the verified module:
331+
332+
To add a rule check to cover the code of all modules, you need to add configuration to the module in which the plugin
333+
is applied (usually this is the root module):
294334

295335
<details open>
296336
<summary>Kotlin</summary>
297337

298338
```kotlin
299339
tasks.koverVerify {
300340
rule {
301-
name = "The project has upper limit on lines covered"
341+
name = "Minimum number of lines covered"
302342
bound {
303-
maxValue = 100000
343+
minValue = 100000
304344
valueType = kotlinx.kover.api.VerificationValueType.COVERED_LINES_COUNT
305345
}
306346
}
@@ -313,7 +353,7 @@ tasks.koverVerify {
313353
}
314354
}
315355
rule {
316-
name = "Minimal line coverage rate in percents"
356+
name = "Minimal line coverage rate in percent"
317357
bound {
318358
minValue = 50
319359
// valueType is kotlinx.kover.api.VerificationValueType.COVERED_LINES_PERCENTAGE by default
@@ -329,9 +369,9 @@ tasks.koverVerify {
329369
```groovy
330370
tasks.koverVerify {
331371
rule {
332-
name = "The project doesn't has upper limit on lines covered"
372+
name = "Minimum number of lines covered"
333373
bound {
334-
maxValue = 100000
374+
minValue = 100000
335375
valueType = 'COVERED_LINES_COUNT'
336376
}
337377
}
@@ -344,7 +384,7 @@ tasks.koverVerify {
344384
}
345385
}
346386
rule {
347-
name = "Minimal line coverage rate in percents"
387+
name = "Minimal line coverage rate in percent"
348388
bound {
349389
minValue = 50
350390
// valueType is 'COVERED_LINES_PERCENTAGE' by default
@@ -354,19 +394,58 @@ tasks.koverVerify {
354394
```
355395
</details>
356396

397+
To add rules for code coverage checks for one specific module, you need to add a configuration to this module:
398+
399+
<details open>
400+
<summary>Kotlin</summary>
401+
402+
```kotlin
403+
tasks.koverModuleVerify {
404+
rule {
405+
name = "Minimal line coverage rate in percent"
406+
bound {
407+
minValue = 75
408+
}
409+
}
410+
}
411+
```
412+
</details>
413+
414+
<details>
415+
<summary>Groovy</summary>
416+
417+
```groovy
418+
tasks.koverModuleVerify {
419+
rule {
420+
name = "Minimal line coverage rate in percent"
421+
bound {
422+
minValue = 75
423+
}
424+
}
425+
}
426+
```
427+
</details>
428+
429+
357430
## Tasks
358-
The plugin, when applied, automatically creates tasks for the module (all modules, if the project is multi-module, and it applied in root build script):
359-
- `koverXmlReport` - Generates code coverage XML report for all module's test tasks.
360-
- `koverHtmlReport` - Generates code coverage HTML report for all module's test tasks.
361-
- `koverReport` - Executes both `koverXmlReport` and `koverHtmlReport` tasks.
362-
- `koverCollectReports` - Collects reports from all submodules in one directory. Default directory is `$buildDir/reports/kover/all`, names for XML reports and dirs for HTML are projects names. Executing this task does not run `koverXmlReport` or `koverHtmlReport`, it only copies previously created reports if they exist to the output directory.
363-
- `koverVerify` - Verifies code coverage metrics based on specified rules. Always executes before `check` task.
431+
The plugin, when applied, automatically creates tasks for the module in which it is applied (usually this is the root module):
432+
- `koverHtmlReport` - Generates code coverage HTML report for all enabled test tasks in all modules.
433+
- `koverXmlReport` - Generates code coverage XML report for all enabled test tasks in all modules.
434+
- `koverReport` - Executes both `koverXmlReport` and `koverHtmlReport` tasks. Executes before `check` task if property `generateReportOnCheck` for `KoverExtension` is `true` ([see](#configuring-entire-plugin)).
435+
- `koverVerify` - Verifies code coverage metrics of all modules based on specified rules. Always executes before `check` task.
436+
- `koverCollectModuleReports` - Collects all modules reports into one directory. Default directory is `$buildDir/reports/kover/modules`, names for XML reports and dirs for HTML are modules names. Executing this task does not run `koverXmlReport` or `koverHtmlReport`, it only copies previously created reports if they exist to the output directory.
437+
438+
Tasks that are created for all modules:
439+
- `koverHtmlModuleReport` - Generates code coverage HTML report for all enabled test tasks in one module.
440+
- `koverXmlModuleReport` - Generates code coverage XML report for all enabled test tasks in one module.
441+
- `koverModuleReport` - Executes both `koverXmlModuleReport` and `koverHtmlModuleReport` tasks.
442+
- `koverModuleVerify` - Verifies code coverage metrics of one module based on specified rules. Always executes before `check` task.
364443

365444

366445
## Implicit plugin dependencies
367446
During the applying of the plugin, the artifacts of the JaCoCo or IntelliJ toolkit are dynamically loaded. They are downloaded from the `mavenCentral` repository.
368447

369-
For the plugin to work correctly, you need to make sure that the `mavenCentral` or its mirror is added to the list by the repository of the module in which the plugin is applied (usually this is the root module of the project) and add it if necessary.
448+
For the plugin to work correctly, you need to make sure that the `mavenCentral` or its mirror is added to the list by the repository of the module in which the plugin is applied (usually this is the root module) and add it if necessary.
370449

371450
<details open>
372451
<summary>Kotlin</summary>

src/functionalTest/kotlin/kotlinx/kover/test/functional/cases/DefaultConfigTests.kt

+5-20
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,15 @@ import kotlin.test.*
66

77
internal class DefaultConfigTests : BaseGradleScriptTest() {
88
@Test
9-
fun testImplicitConfigsJvm() {
10-
builder()
11-
.case("Test default setting for Kotlin/JVM")
9+
fun testImplicitConfigs() {
10+
builder("Test implicit default settings")
1211
.languages(GradleScriptLanguage.GROOVY, GradleScriptLanguage.KOTLIN)
13-
.types(ProjectType.KOTLIN_JVM)
12+
.types(ProjectType.KOTLIN_JVM, ProjectType.KOTLIN_MULTIPLATFORM)
1413
.sources("simple")
1514
.build()
1615
.run("build") {
17-
checkIntellijBinaryReport(DEFAULT_INTELLIJ_KJVM_BINARY, DEFAULT_INTELLIJ_KJVM_SMAP)
18-
checkReports(DEFAULT_XML, DEFAULT_HTML)
19-
}
20-
}
21-
22-
@Test
23-
fun testImplicitConfigsKmp() {
24-
builder()
25-
.case("Test default setting for Kotlin Multi-Platform")
26-
.languages(GradleScriptLanguage.GROOVY, GradleScriptLanguage.KOTLIN)
27-
.types(ProjectType.KOTLIN_MULTIPLATFORM)
28-
.sources("simple")
29-
.build()
30-
.run("build") {
31-
checkIntellijBinaryReport(DEFAULT_INTELLIJ_KMP_BINARY, DEFAULT_INTELLIJ_KMP_SMAP)
32-
checkReports(DEFAULT_XML, DEFAULT_HTML)
16+
checkDefaultBinaryReport()
17+
checkDefaultReports()
3318
}
3419
}
3520

src/functionalTest/kotlin/kotlinx/kover/test/functional/cases/InstrumentationFilteringTests.kt

+6-8
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ internal class InstrumentationFilteringTests : BaseGradleScriptTest() {
1010

1111
@Test
1212
fun testExclude() {
13-
builder()
14-
.case("Test exclusion of classes from instrumentation")
13+
builder("Test exclusion of classes from instrumentation")
1514
.languages(GradleScriptLanguage.KOTLIN, GradleScriptLanguage.GROOVY)
1615
.types(ProjectType.KOTLIN_JVM, ProjectType.KOTLIN_MULTIPLATFORM)
1716
.engines(CoverageEngine.INTELLIJ, CoverageEngine.JACOCO)
@@ -22,17 +21,16 @@ internal class InstrumentationFilteringTests : BaseGradleScriptTest() {
2221
)
2322
.build()
2423
.run("build") {
25-
xml(DEFAULT_XML) {
24+
xml(defaultXmlReport()) {
2625
assertCounterExcluded(classCounter("org.jetbrains.ExampleClass"), this@run.engine)
27-
assertCounterCoveredAndIncluded(classCounter("org.jetbrains.SecondClass"))
26+
assertCounterCovered(classCounter("org.jetbrains.SecondClass"))
2827
}
2928
}
3029
}
3130

3231
@Test
3332
fun testExcludeInclude() {
34-
builder()
35-
.case("Test inclusion and exclusion of classes in instrumentation")
33+
builder("Test inclusion and exclusion of classes in instrumentation")
3634
.languages(GradleScriptLanguage.KOTLIN, GradleScriptLanguage.GROOVY)
3735
.types(ProjectType.KOTLIN_JVM, ProjectType.KOTLIN_MULTIPLATFORM)
3836
.engines(CoverageEngine.INTELLIJ, CoverageEngine.JACOCO)
@@ -47,10 +45,10 @@ internal class InstrumentationFilteringTests : BaseGradleScriptTest() {
4745
)
4846
.build()
4947
.run("build") {
50-
xml(DEFAULT_XML) {
48+
xml(defaultXmlReport()) {
5149
assertCounterExcluded(classCounter("org.jetbrains.ExampleClass"), this@run.engine)
5250
assertCounterExcluded(classCounter("org.jetbrains.Unused"), this@run.engine)
53-
assertCounterCoveredAndIncluded(classCounter("org.jetbrains.SecondClass"))
51+
assertCounterCovered(classCounter("org.jetbrains.SecondClass"))
5452
}
5553
}
5654
}

0 commit comments

Comments
 (0)