Browse Source
* Don't apply Kover to projects with AAR libraries * Move the Kover configuration to the `plugins` projectpull/2220/head
Jorge Martin Espinosa
8 months ago
committed by
GitHub
7 changed files with 248 additions and 203 deletions
@ -0,0 +1,229 @@
@@ -0,0 +1,229 @@
|
||||
/* |
||||
* Copyright (c) 2024 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package extension |
||||
|
||||
import kotlinx.kover.gradle.plugin.dsl.KoverReportExtension |
||||
import org.gradle.api.Action |
||||
import org.gradle.api.Project |
||||
import org.gradle.kotlin.dsl.apply |
||||
|
||||
val localAarProjects = listOf( |
||||
":libraries:rustsdk", |
||||
":libraries:textcomposer:lib" |
||||
) |
||||
|
||||
val excludedKoverSubProjects = listOf( |
||||
":app", |
||||
":samples", |
||||
":anvilannotations", |
||||
":anvilcodegen", |
||||
":samples:minimal", |
||||
":tests:testutils", |
||||
// Exclude `:libraries:matrix:impl` module, it contains only wrappers to access the Rust Matrix |
||||
// SDK api, so it is not really relevant to unit test it: there is no logic to test. |
||||
":libraries:matrix:impl", |
||||
// Exclude modules which are not Android libraries |
||||
// See https://github.com/Kotlin/kotlinx-kover/issues/312 |
||||
":appconfig", |
||||
":libraries:core", |
||||
":libraries:coroutines", |
||||
":libraries:di", |
||||
) + localAarProjects |
||||
|
||||
private fun Project.koverReport(action: Action<KoverReportExtension>) { |
||||
(this as org.gradle.api.plugins.ExtensionAware).extensions.configure("koverReport", action) |
||||
} |
||||
|
||||
fun Project.setupKover() { |
||||
// https://kotlin.github.io/kotlinx-kover/ |
||||
// Run `./gradlew :app:koverHtmlReport` to get report at ./app/build/reports/kover |
||||
// Run `./gradlew :app:koverXmlReport` to get XML report |
||||
koverReport { |
||||
filters { |
||||
excludes { |
||||
classes( |
||||
// Exclude generated classes. |
||||
"*_ModuleKt", |
||||
"anvil.hint.binding.io.element.*", |
||||
"anvil.hint.merge.*", |
||||
"anvil.hint.multibinding.io.element.*", |
||||
"anvil.module.*", |
||||
"com.airbnb.android.showkase*", |
||||
"io.element.android.libraries.designsystem.showkase.*", |
||||
"io.element.android.x.di.DaggerAppComponent*", |
||||
"*_Factory", |
||||
"*_Factory_Impl", |
||||
"*_Factory$*", |
||||
"*_Module", |
||||
"*_Module$*", |
||||
"*Module_Provides*", |
||||
"Dagger*Component*", |
||||
"*ComposableSingletons$*", |
||||
"*_AssistedFactory_Impl*", |
||||
"*BuildConfig", |
||||
// Generated by Showkase |
||||
"*Ioelementandroid*PreviewKt$*", |
||||
"*Ioelementandroid*PreviewKt", |
||||
// Other |
||||
// We do not cover Nodes (normally covered by maestro, but code coverage is not computed with maestro) |
||||
"*Node", |
||||
"*Node$*", |
||||
"*Presenter\$present\$*", |
||||
// Forked from compose |
||||
"io.element.android.libraries.designsystem.theme.components.bottomsheet.*", |
||||
) |
||||
annotatedBy( |
||||
"androidx.compose.ui.tooling.preview.Preview", |
||||
"io.element.android.libraries.architecture.coverage.ExcludeFromCoverage", |
||||
"io.element.android.libraries.designsystem.preview.PreviewsDayNight", |
||||
"io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight", |
||||
) |
||||
} |
||||
} |
||||
|
||||
defaults { |
||||
// add reports of both 'debug' and 'release' Android build variants to default reports |
||||
mergeWith("debug") |
||||
mergeWith("release") |
||||
|
||||
verify { |
||||
onCheck = true |
||||
// General rule: minimum code coverage. |
||||
rule("Global minimum code coverage.") { |
||||
isEnabled = true |
||||
entity = kotlinx.kover.gradle.plugin.dsl.GroupingEntityType.APPLICATION |
||||
bound { |
||||
minValue = 65 |
||||
// Setting a max value, so that if coverage is bigger, it means that we have to change minValue. |
||||
// For instance if we have minValue = 20 and maxValue = 30, and current code coverage is now 31.32%, update |
||||
// minValue to 25 and maxValue to 35. |
||||
maxValue = 75 |
||||
metric = kotlinx.kover.gradle.plugin.dsl.MetricType.INSTRUCTION |
||||
aggregation = kotlinx.kover.gradle.plugin.dsl.AggregationType.COVERED_PERCENTAGE |
||||
} |
||||
} |
||||
// Rule to ensure that coverage of Presenters is sufficient. |
||||
rule("Check code coverage of presenters") { |
||||
isEnabled = true |
||||
entity = kotlinx.kover.gradle.plugin.dsl.GroupingEntityType.CLASS |
||||
filters { |
||||
includes { |
||||
classes( |
||||
"*Presenter", |
||||
) |
||||
} |
||||
excludes { |
||||
classes( |
||||
"*Fake*Presenter", |
||||
"io.element.android.appnav.loggedin.LoggedInPresenter$*", |
||||
// Some options can't be tested at the moment |
||||
"io.element.android.features.preferences.impl.developer.DeveloperSettingsPresenter$*", |
||||
"*Presenter\$present\$*", |
||||
) |
||||
} |
||||
} |
||||
bound { |
||||
minValue = 85 |
||||
metric = kotlinx.kover.gradle.plugin.dsl.MetricType.INSTRUCTION |
||||
aggregation = kotlinx.kover.gradle.plugin.dsl.AggregationType.COVERED_PERCENTAGE |
||||
} |
||||
} |
||||
// Rule to ensure that coverage of States is sufficient. |
||||
rule("Check code coverage of states") { |
||||
isEnabled = true |
||||
entity = kotlinx.kover.gradle.plugin.dsl.GroupingEntityType.CLASS |
||||
filters { |
||||
includes { |
||||
classes( |
||||
"^*State$", |
||||
) |
||||
} |
||||
excludes { |
||||
classes( |
||||
"io.element.android.appnav.root.RootNavState*", |
||||
"io.element.android.libraries.matrix.api.timeline.item.event.OtherState$*", |
||||
"io.element.android.libraries.matrix.api.timeline.item.event.EventSendState$*", |
||||
"io.element.android.libraries.matrix.api.room.RoomMembershipState*", |
||||
"io.element.android.libraries.matrix.api.room.MatrixRoomMembersState*", |
||||
"io.element.android.libraries.push.impl.notifications.NotificationState*", |
||||
"io.element.android.features.messages.impl.media.local.pdf.PdfViewerState", |
||||
"io.element.android.features.messages.impl.media.local.LocalMediaViewState", |
||||
"io.element.android.features.location.impl.map.MapState*", |
||||
"io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState*", |
||||
"io.element.android.libraries.designsystem.swipe.SwipeableActionsState*", |
||||
"io.element.android.features.messages.impl.timeline.components.ExpandableState*", |
||||
"io.element.android.features.messages.impl.timeline.model.bubble.BubbleState*", |
||||
"io.element.android.libraries.maplibre.compose.CameraPositionState*", |
||||
"io.element.android.libraries.maplibre.compose.SaveableCameraPositionState", |
||||
"io.element.android.libraries.maplibre.compose.SymbolState*", |
||||
"io.element.android.features.ftue.api.state.*", |
||||
"io.element.android.features.ftue.impl.welcome.state.*", |
||||
) |
||||
} |
||||
} |
||||
bound { |
||||
minValue = 90 |
||||
metric = kotlinx.kover.gradle.plugin.dsl.MetricType.INSTRUCTION |
||||
aggregation = kotlinx.kover.gradle.plugin.dsl.AggregationType.COVERED_PERCENTAGE |
||||
} |
||||
} |
||||
// Rule to ensure that coverage of Views is sufficient (deactivated for now). |
||||
rule("Check code coverage of views") { |
||||
isEnabled = true |
||||
entity = kotlinx.kover.gradle.plugin.dsl.GroupingEntityType.CLASS |
||||
filters { |
||||
includes { |
||||
classes( |
||||
"*ViewKt", |
||||
) |
||||
} |
||||
} |
||||
bound { |
||||
// TODO Update this value, for now there are too many missing tests. |
||||
minValue = 0 |
||||
metric = kotlinx.kover.gradle.plugin.dsl.MetricType.INSTRUCTION |
||||
aggregation = kotlinx.kover.gradle.plugin.dsl.AggregationType.COVERED_PERCENTAGE |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
androidReports("release") {} |
||||
} |
||||
} |
||||
|
||||
fun Project.applyKoverPluginToAllSubProjects() = rootProject.allprojects { |
||||
if (project.path !in localAarProjects) { |
||||
apply(plugin = "org.jetbrains.kotlinx.kover") |
||||
} |
||||
} |
||||
|
||||
fun Project.koverDependencies() { |
||||
project.rootProject.subprojects |
||||
.filter { |
||||
it.project.projectDir.resolve("build.gradle.kts").exists() |
||||
} |
||||
.map { it.path } |
||||
.sorted() |
||||
.filter { |
||||
it !in excludedKoverSubProjects |
||||
} |
||||
.forEach { |
||||
// println("Add $it to kover") |
||||
dependencies.add("kover", project(it)) |
||||
} |
||||
} |
Loading…
Reference in new issue