Closed NinoDLC closed 2 years ago
Hi, in the current version of the API, the filter for instrumentation and the filter for reports are configuring in different places. In your example, you excluded a class from instrumentation - in this case, coverage for such a class will always be 0 in the report.
To exclude a class from a report, you just need to add an exclusion rule to the report generation task:
tasks.koverHtmlReport {
excludes = [
"*_*Factory.*",
"*_Factory.*",
"Hilt_*",
"*_Hilt*",
]
}
In the upcoming releases, the API will be redesigned and it will be enough to specify the filter only in one place.
Duplicates #162
I tried that too, I put that code in build.gradle
(project), then ./gradlew clean koverHtmlReport
, but nothing changed in the report.
tasks.koverHtmlReport {
excludes = [
"*_*Factory.*",
"*_Factory.*",
"Hilt_*",
"*_Hilt*",
]
}
You can check my gradle files (and / or generate the report) here : https://github.com/NinoDLC/Pokedexino
You need to put the configuration
tasks.koverHtmlReport {
excludes = [
"*_*Factory.*",
"*_Factory.*",
"Hilt_*",
"*_Hilt*",
]
}
in build.gradle
module file
Then, for example, the following report is generated for the package fr.delcey.pokedexino.ui.detail
As far as I understand, the class fr.delcey.pokedexino.ui.detail.PokemonDetailViewModel_Factory
should also be excluded from the report, for this it is necessary to remove the dot from the rule "*_Factory.*"
, because there is no dot at the end of the fully-qualified class name.
With
tasks.koverHtmlReport {
excludes = [
"*_*Factory*",
"*_Factory*",
"Hilt_*",
"*_Hilt*",
]
}
report is
Thanks a lot ! Gradle is such a weird mess.
Still, I can't manage to exclude a file prefixed with Hilt_
. As seen in the screenshot, Hilt_PokemonDetailFragment
is still present even with the exclude pattern "Hilt_*"
.
If I use "**/Hilt_*"
, it doesn't work any better (it should, right ?). Interestingly, "*/Hilt_*"
doesn't work either
If I use "*Hilt_*"
, it works, but this isn't a perfect solution.
Is it a bug or a (currently missing) feature ?
Please note that the Kover works with fully-qualified class names.
Hilt_PokemonDetailFragment
is a simple class name, fr.delcey.pokedexino.ui.detail.Hilt_PokemonDetailFragment
is a fully-qualified name.
Thus, if you want to exclude such a class, you need to write such a rule *.Hilt_*
(so you exclude any class from non-root package with simple name started with Hilt_
)
You mention fully-qualified class names, but is the type also somewhat considered ? I've got a weird behavior about that.
If I use the rule "*_Impl"
, my fr.delcey.pokedexino.data.AppDatabase_Impl
is not excluded.
If I use the rule "*_Impl*"
, my fr.delcey.pokedexino.data.AppDatabase_Impl
is excluded.
If I use the rule "*_Impl.java"
, my fr.delcey.pokedexino.data.AppDatabase_Impl
is not excluded.
If I use the rule "*_Impl.kt"
, my fr.delcey.pokedexino.data.AppDatabase_Impl
is not excluded.
If I use the rule "*_Impl.*"
, my fr.delcey.pokedexino.data.AppDatabase_Impl
is not excluded.
Note that AppDatabase_Impl
is a generated .java
file.
No, file name extensions are never part of a class name in Java or in Kotlin.
Most likely, you were confused by the fact that the rule *_Impl
did not work.
Here the situation was complicated by the peculiarity of the JVM and the reporter.
If a class contains a nested class or a lambda expression, then a class with the same name is created in the JVM, but $smth
is added at the end.
If you open the AppDatabase_Impl
class in the report, you will see that the coverage is shown inside only for the AppDatabase_Impl$1
class (it looks like the class contained a lambda expression).
To completely eliminate such situations , you can add two rules
"*_Impl",
"*_Impl\$*"
Very interesting! Thanks a lot for your time and explainations :)
Out of thoughts, shouldn't nested classes or lambda expressions be automatically excluded if their englobing classes are excluded ?
Out of thoughts, shouldn't nested classes or lambda expressions be automatically excluded if their englobing classes are excluded ?
This is an ambiguous issue.
Nested classes definitely cannot be excluded, but lambdas are very often difficult to distinguish from custom classes.
Therefore, at the moment, the exception via "*name$*"
remains the most versatile and flexible way.
For any future Googler (if any), here's my full implementation for excluding Hilt generated files with Kover.
build.gradle
(module) :
def excludedFromCoverage = [
"dagger.hilt.*",
"hilt_aggregated_deps.*",
"*_Factory",
"*_Factory\$*",
"*_*Factory",
"*_*Factory\$*",
"*.Hilt_*",
"*_HiltModules",
"*_HiltModules\$*",
"*_Impl",
"*_Impl\$*",
"*.AppModule", // Your Hilt modules should be there if you don't want to test them
"*.DataModule",
"*.DomainModule",
]
...
android {
testOptions {
unitTests.all {
if (it.name == "testReleaseUnitTest") {
kover {
disabled = false
excludes = excludedFromCoverage
}
} else if (it.name == "testDebugUnitTest") {
kover {
disabled = true // won't run unit tests twice (once in debug mode, once in release mode)
}
}
}
}
}
...
tasks.koverHtmlReport {
excludes = excludedFromCoverage
}
PS: Current version is 0.5, it is likely that future versions will simplify the excluding of files.
In my case, excludes = listOf("*")
setting in unitTests and koverHtmlReport does not effect. (Kover 0.5.1)
I'll wait next release... 😢
In my case,
excludes = listOf("*")
setting in unitTests and koverHtmlReport does not effect. (Kover 0.5.1)I'll wait next release... 😢
What are you trying to achieve ? With *
you'd just exclude every single file from coverage, so why use Kover at all ?
Sorry not enough explanation. I'd like to know whether Kover recognize the exclude options or not by setting excludes = listOf("*")
. But the result has all classes, so I think the eclude options are not recognized.
Today, I try again, then the excludes option works correctly 👍
I already discarded commit log of https://github.com/Kotlin/kotlinx-kover/issues/186#issuecomment-1157688405, so I can't discover what my mistake was. sorry...
This is working configuration in my project:
build.gradle.kts
plugins {
...
id("org.jetbrains.kotlinx.kover") version "0.5.1"
}
...
android {
...
testOptions {
unitTests.all {
it.configure<KoverTaskExtension> {
isDisabled = !it.name.contains("Debug") // only executes test for debug build type
excludes = listOf("*") // "*" ignores all classes, so it results empty report.
}
}
}
}
tasks.koverHtmlReport {
excludes = listOf("*") // "*" ignores all classes, so it results empty report.
}
Hi, in the current version of the API, the filter for instrumentation and the filter for reports are configuring in different places. In your example, you excluded a class from instrumentation - in this case, coverage for such a class will always be 0 in the report.
To exclude a class from a report, you just need to add an exclusion rule to the report generation task:
tasks.koverHtmlReport { excludes = [ "*_*Factory.*", "*_Factory.*", "Hilt_*", "*_Hilt*", ] }
In the upcoming releases, the API will be redesigned and it will be enough to specify the filter only in one place.
Duplicates #162
Hi @shanshin , As you said that I understood, when we add an exclusion for a class or package, we exclude only from instrumentation, The classes that we excluded, they continues to stay on the coverage report but they have zero coverage rate. Did I understand correctly ?
Thank you.
@tugceaktepe, hi, the API has been redesigned in the latest version. For which version is your question relevant?
Hi @shanshin I mean version 0.6.0.
build.gradle (project)
build.gradle (android module)
In the report (generated by
./gradlew clean koverHtmlReport
), no file is excluded: