Skip to content

Commit

Permalink
Implemented aggregate reports
Browse files Browse the repository at this point in the history
Resolves #20, #43
  • Loading branch information
shanshin committed Dec 9, 2021
1 parent 1475b5d commit 743c509
Show file tree
Hide file tree
Showing 41 changed files with 1,144 additions and 476 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
@@ -1,4 +1,4 @@
version=0.4.4
version=0.4.5
group=org.jetbrains.kotlinx

kotlin.code.style=official
Expand Up @@ -6,30 +6,15 @@ import kotlin.test.*

internal class DefaultConfigTests : BaseGradleScriptTest() {
@Test
fun testImplicitConfigsJvm() {
builder()
.case("Test default setting for Kotlin/JVM")
fun testImplicitConfigs() {
builder("Test implicit default settings")
.languages(GradleScriptLanguage.GROOVY, GradleScriptLanguage.KOTLIN)
.types(ProjectType.KOTLIN_JVM)
.types(ProjectType.KOTLIN_JVM, ProjectType.KOTLIN_MULTIPLATFORM)
.sources("simple")
.build()
.run("build") {
checkIntellijBinaryReport(DEFAULT_INTELLIJ_KJVM_BINARY, DEFAULT_INTELLIJ_KJVM_SMAP)
checkReports(DEFAULT_XML, DEFAULT_HTML)
}
}

@Test
fun testImplicitConfigsKmp() {
builder()
.case("Test default setting for Kotlin Multi-Platform")
.languages(GradleScriptLanguage.GROOVY, GradleScriptLanguage.KOTLIN)
.types(ProjectType.KOTLIN_MULTIPLATFORM)
.sources("simple")
.build()
.run("build") {
checkIntellijBinaryReport(DEFAULT_INTELLIJ_KMP_BINARY, DEFAULT_INTELLIJ_KMP_SMAP)
checkReports(DEFAULT_XML, DEFAULT_HTML)
checkDefaultBinaryReport()
checkDefaultReports()
}
}

Expand Down
Expand Up @@ -10,8 +10,7 @@ internal class InstrumentationFilteringTests : BaseGradleScriptTest() {

@Test
fun testExclude() {
builder()
.case("Test exclusion of classes from instrumentation")
builder("Test exclusion of classes from instrumentation")
.languages(GradleScriptLanguage.KOTLIN, GradleScriptLanguage.GROOVY)
.types(ProjectType.KOTLIN_JVM, ProjectType.KOTLIN_MULTIPLATFORM)
.engines(CoverageEngine.INTELLIJ, CoverageEngine.JACOCO)
Expand All @@ -22,17 +21,16 @@ internal class InstrumentationFilteringTests : BaseGradleScriptTest() {
)
.build()
.run("build") {
xml(DEFAULT_XML) {
xml(defaultXmlReport()) {
assertCounterExcluded(classCounter("org.jetbrains.ExampleClass"), this@run.engine)
assertCounterCoveredAndIncluded(classCounter("org.jetbrains.SecondClass"))
assertCounterCovered(classCounter("org.jetbrains.SecondClass"))
}
}
}

@Test
fun testExcludeInclude() {
builder()
.case("Test inclusion and exclusion of classes in instrumentation")
builder("Test inclusion and exclusion of classes in instrumentation")
.languages(GradleScriptLanguage.KOTLIN, GradleScriptLanguage.GROOVY)
.types(ProjectType.KOTLIN_JVM, ProjectType.KOTLIN_MULTIPLATFORM)
.engines(CoverageEngine.INTELLIJ, CoverageEngine.JACOCO)
Expand All @@ -47,10 +45,10 @@ internal class InstrumentationFilteringTests : BaseGradleScriptTest() {
)
.build()
.run("build") {
xml(DEFAULT_XML) {
xml(defaultXmlReport()) {
assertCounterExcluded(classCounter("org.jetbrains.ExampleClass"), this@run.engine)
assertCounterExcluded(classCounter("org.jetbrains.Unused"), this@run.engine)
assertCounterCoveredAndIncluded(classCounter("org.jetbrains.SecondClass"))
assertCounterCovered(classCounter("org.jetbrains.SecondClass"))
}
}
}
Expand Down
@@ -0,0 +1,67 @@
package kotlinx.kover.test.functional.cases

import kotlinx.kover.api.*
import kotlinx.kover.test.functional.cases.utils.*
import kotlinx.kover.test.functional.cases.utils.defaultXmlReport
import kotlinx.kover.test.functional.core.BaseGradleScriptTest
import kotlinx.kover.test.functional.core.GradleScriptLanguage
import kotlinx.kover.test.functional.core.ProjectType
import kotlin.test.*

internal class MultiModulesTest : BaseGradleScriptTest() {
@Test
fun testAggregateReports() {
builder("Testing the generation of aggregating reports")
.languages(GradleScriptLanguage.KOTLIN, GradleScriptLanguage.GROOVY)
.types(ProjectType.KOTLIN_JVM, ProjectType.KOTLIN_MULTIPLATFORM)
.engines(CoverageEngine.INTELLIJ, CoverageEngine.JACOCO)
.sources("multimodule-B")
.submodule("submodule") {
sources("multimodule-A")
}
.dependency(
"implementation(project(\":submodule\"))",
"implementation project(':submodule')"
)
.build()
.run("build") {
xml(defaultXmlReport()) {
assertCounterFullyCovered(classCounter("org.jetbrains.CommonClass"))
assertCounterFullyCovered(classCounter("org.jetbrains.AClass"))
assertCounterFullyCovered(classCounter("org.jetbrains.BClass"))
}
}
}

@Test
fun testModuleReports() {
builder("Testing the generation of module reports")
.languages(GradleScriptLanguage.KOTLIN, GradleScriptLanguage.GROOVY)
.types(ProjectType.KOTLIN_JVM, ProjectType.KOTLIN_MULTIPLATFORM)
.engines(CoverageEngine.INTELLIJ, CoverageEngine.JACOCO)
.sources("multimodule-B")
.submodule("submodule") {
sources("multimodule-A")
}
.dependency(
"implementation(project(\":submodule\"))",
"implementation project(':submodule')"
)
.build()
.run("koverModuleReport") {
xml(defaultXmlModuleReport()) {
assertCounterMissed(classCounter("org.jetbrains.CommonClass"))
assertCounterMissed(classCounter("org.jetbrains.AClass"))
assertCounterFullyCovered(classCounter("org.jetbrains.BClass"))
}

submodule("submodule") {
xml(defaultXmlModuleReport()) {
assertCounterFullyCovered(classCounter("org.jetbrains.CommonClass"))
assertCounterFullyCovered(classCounter("org.jetbrains.AClass"))
assertCounterMissed(classCounter("org.jetbrains.BClass"))
}
}
}
}
}
Expand Up @@ -8,51 +8,48 @@ import kotlin.test.*

internal class ReportsCachingTests : BaseGradleScriptTest() {
@Test
fun testCachingForIntellij() {
builder()
.case("Test caching reports for IntelliJ Coverage Engine")
.engines(CoverageEngine.INTELLIJ)
fun testCaching() {
builder("Test caching aggregate reports")
.engines(CoverageEngine.INTELLIJ, CoverageEngine.JACOCO)
.sources("simple")
.build()
.run("build", "--build-cache") {
checkIntellijBinaryReport(DEFAULT_INTELLIJ_KJVM_BINARY, DEFAULT_INTELLIJ_KJVM_SMAP)
checkReports(DEFAULT_XML, DEFAULT_HTML)
checkDefaultBinaryReport()
checkDefaultReports()
}
.run("clean", "--build-cache") {
checkIntellijBinaryReport(DEFAULT_INTELLIJ_KJVM_BINARY, DEFAULT_INTELLIJ_KJVM_SMAP, false)
checkReports(DEFAULT_XML, DEFAULT_HTML, false)
checkDefaultBinaryReport(false)
checkDefaultReports(false)
}
.run("build", "--build-cache") {
checkIntellijBinaryReport(DEFAULT_INTELLIJ_KJVM_BINARY, DEFAULT_INTELLIJ_KJVM_SMAP)
checkReports(DEFAULT_XML, DEFAULT_HTML)
outcome(":test") { assertEquals(TaskOutcome.FROM_CACHE, this)}
outcome(":koverXmlReport") { assertEquals(TaskOutcome.FROM_CACHE, this)}
outcome(":koverHtmlReport") { assertEquals(TaskOutcome.FROM_CACHE, this)}
checkDefaultBinaryReport()
checkDefaultReports()
outcome(":test") { assertEquals(TaskOutcome.FROM_CACHE, this) }
outcome(":koverXmlReport") { assertEquals(TaskOutcome.FROM_CACHE, this) }
outcome(":koverHtmlReport") { assertEquals(TaskOutcome.FROM_CACHE, this) }
}
}

@Test
fun testCachingForJacoco() {
builder()
.case("Test caching reports for JaCoCo Coverage Engine")
.engines(CoverageEngine.JACOCO)
fun testModuleCaching() {
builder("Test caching module reports")
.engines(CoverageEngine.INTELLIJ, CoverageEngine.JACOCO)
.sources("simple")
.build()
.run("build", "--build-cache") {
checkJacocoBinaryReport(DEFAULT_JACOCO_KJVM_BINARY)
checkReports(DEFAULT_XML, DEFAULT_HTML)
.run("koverModuleReport", "--build-cache") {
checkDefaultBinaryReport()
checkDefaultModuleReports()
}
.run("clean", "--build-cache") {
checkJacocoBinaryReport(DEFAULT_JACOCO_KJVM_BINARY, false)
checkReports(DEFAULT_XML, DEFAULT_HTML, false)
checkDefaultBinaryReport(false)
checkDefaultModuleReports(false)
}
.run("build", "--build-cache") {
checkJacocoBinaryReport(DEFAULT_JACOCO_KJVM_BINARY)
checkReports(DEFAULT_XML, DEFAULT_HTML)

outcome(":test") { assertEquals(TaskOutcome.FROM_CACHE, this)}
outcome(":koverXmlReport") { assertEquals(TaskOutcome.FROM_CACHE, this)}
outcome(":koverHtmlReport") { assertEquals(TaskOutcome.FROM_CACHE, this)}
.run("koverModuleReport", "--build-cache") {
checkDefaultBinaryReport()
checkDefaultModuleReports()
outcome(":test") { assertEquals(TaskOutcome.FROM_CACHE, this) }
outcome(":koverXmlModuleReport") { assertEquals(TaskOutcome.FROM_CACHE, this) }
outcome(":koverHtmlModuleReport") { assertEquals(TaskOutcome.FROM_CACHE, this) }
}
}

Expand Down
Expand Up @@ -5,43 +5,48 @@ import kotlinx.kover.test.functional.core.*
import kotlinx.kover.test.functional.core.RunResult
import kotlin.test.*

internal fun RunResult.checkIntellijBinaryReport(binary: String, smap: String, mustExists: Boolean = true) {
internal fun RunResult.checkDefaultBinaryReport(mustExists: Boolean = true) {
val binary: String = defaultBinaryReport(engine, projectType)

if (mustExists) {
file(binary) {
assertTrue { exists() }
assertTrue { length() > 0 }
}
file(smap) {
assertTrue { exists() }
assertTrue { length() > 0 }
}
} else {
file(binary) {
assertFalse { exists() }
}
file(smap) {
assertFalse { exists() }
}
}
}

internal fun RunResult.checkJacocoBinaryReport(binary: String, mustExists: Boolean = true) {
if (mustExists) {
file(binary) {
assertTrue { exists() }
assertTrue { length() > 0 }
}
} else {
file(binary) {
assertFalse { exists() }
if (engine == CoverageEngine.INTELLIJ) {
val smap = defaultSmapFile(projectType)

if (mustExists) {
file(smap) {
assertTrue { exists() }
assertTrue { length() > 0 }
}
} else {
file(smap) {
assertFalse { exists() }
}
}
}
}

internal fun RunResult.checkReports(xmlPath: String, htmlPath: String, mustExists: Boolean = true) {
internal fun RunResult.checkDefaultReports(mustExists: Boolean = true) {
checkReports(defaultXmlReport(), defaultHtmlReport(), mustExists)
}

internal fun RunResult.checkDefaultModuleReports(mustExists: Boolean = true) {
checkReports(defaultXmlModuleReport(), defaultHtmlModuleReport(), mustExists)
}

private fun RunResult.checkReports(xmlPath: String, htmlPath: String, mustExists: Boolean) {
if (mustExists) {
file(xmlPath) {
assertTrue { exists() }
assertTrue("XML file must exist '$xmlPath'") { exists() }
assertTrue { length() > 0 }
}
file(htmlPath) {
Expand All @@ -58,6 +63,10 @@ internal fun RunResult.checkReports(xmlPath: String, htmlPath: String, mustExist
}
}

internal fun assertCounterMissed(counter: Counter?) {
assertNull(counter)
}

internal fun assertCounterExcluded(counter: Counter?, engine: CoverageEngine) {
if (engine == CoverageEngine.INTELLIJ) {
assertNull(counter)
Expand All @@ -67,7 +76,15 @@ internal fun assertCounterExcluded(counter: Counter?, engine: CoverageEngine) {
}
}

internal fun assertCounterCoveredAndIncluded(counter: Counter?) {
internal fun assertCounterCovered(counter: Counter?) {
assertNotNull(counter)
assertTrue { counter.covered > 0 }
}

internal fun assertCounterFullyCovered(counter: Counter?) {
assertNotNull(counter)
assertTrue { counter.covered > 0 }
assertEquals(0, counter.missed)
}


@@ -1,14 +1,24 @@
package kotlinx.kover.test.functional.cases.utils

import kotlinx.kover.api.*
import kotlinx.kover.test.functional.core.ProjectType

internal const val DEFAULT_INTELLIJ_KJVM_BINARY = "kover/test.ic"
internal const val DEFAULT_INTELLIJ_KJVM_SMAP = "kover/test.ic.smap"

internal const val DEFAULT_INTELLIJ_KMP_BINARY = "kover/jvmTest.ic"
internal const val DEFAULT_INTELLIJ_KMP_SMAP = "kover/jvmTest.ic.smap"
internal fun defaultBinaryReport(engine: CoverageEngine, projectType: ProjectType): String {
val extension = if (engine == CoverageEngine.INTELLIJ) "ic" else "exec"
return when (projectType) {
ProjectType.KOTLIN_JVM -> "kover/test.$extension"
ProjectType.KOTLIN_MULTIPLATFORM -> "kover/jvmTest.$extension"
ProjectType.ANDROID -> "kover/jvmTest.$extension"
}
}

internal const val DEFAULT_JACOCO_KJVM_BINARY = "kover/test.exec"
internal const val DEFAULT_JACOCO_KMP_BINARY = "kover/jvmTest.exec"
internal fun defaultSmapFile(projectType: ProjectType): String {
return defaultBinaryReport(CoverageEngine.INTELLIJ, projectType) + ".smap"
}

internal const val DEFAULT_XML = "reports/kover/report.xml"
internal const val DEFAULT_HTML = "reports/kover/html"
internal fun defaultXmlReport() = "reports/kover/report.xml"
internal fun defaultHtmlReport() = "reports/kover/html"

internal fun defaultXmlModuleReport() = "reports/kover/module-xml/report.xml"
internal fun defaultHtmlModuleReport() = "reports/kover/module-html"
Expand Up @@ -9,7 +9,7 @@ internal open class BaseGradleScriptTest {
@JvmField
internal val rootFolder: TemporaryFolder = TemporaryFolder()

fun builder(): ProjectBuilder {
return createBuilder(rootFolder.root)
fun builder(description: String): ProjectBuilder {
return createBuilder(rootFolder.root, description)
}
}

0 comments on commit 743c509

Please sign in to comment.