Skip to content

Commit

Permalink
Add Android example project
Browse files Browse the repository at this point in the history
  • Loading branch information
NinoDLC committed Sep 30, 2022
1 parent 55173f6 commit 562d11c
Show file tree
Hide file tree
Showing 76 changed files with 2,151 additions and 29 deletions.
120 changes: 92 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,54 +158,118 @@ tasks.test {
```
</details>

**For other platforms (Android, Kotlin-Multiplatform) the names may differ, and you may also have several test tasks, so you first need to determine the name of the required task.**
**For other platforms (like Kotlin-Multiplatform), the names may differ and you may also have several test tasks, so you first need to determine the name of the required task.**


### Configuring Android test task

Example of configuring test task for build type `debug` in Android:
<details open>
<summary>Kotlin</summary>

`build.gradle.kts` (Project)
```kotlin
android {
// other Android declarations

testOptions {
unitTests.all {
if (it.name == "testDebugUnitTest") {
it.extensions.configure(kotlinx.kover.api.KoverTaskExtension::class) {
isDisabled = false // true to disable instrumentation tests of this task, Kover reports will not depend on the results of their execution
binaryReportFile.set(file("$buildDir/custom/debug-report.bin")) // set file name of binary report
includes = listOf("com.example.*") // see "Instrumentation inclusion rules" below
excludes = listOf("com.example.subpackage.*") // see "Instrumentation exclusion rules" below
}
}
buildscript {
// ...
dependencies {
// ...
classpath("org.jetbrains.kotlinx:kover:0.6.0")
}
}

plugins {
id("org.jetbrains.kotlinx.kover") version "0.6.0"
}

koverMerged {
enable()

filters {
classes {
excludes.addAll(
listOf(
"*Fragment",
"*Fragment\$*",
"*Activity",
"*Activity\$*",
"*.databinding.*", // ViewBinding
"org.jetbrains.kover_android_kts_example.BuildConfig"
)
)
}
}
}
```


`build.gradle.kts` (Module)
```kotlin
plugins {
// ...
id("org.jetbrains.kotlinx.kover")
}

android {
// ...
}

dependencies {
// ...
}

kover {
instrumentation {
excludeTasks.add "testReleaseUnitTest"
}
}
```

An example is available here: https://github.com/Kotlin/kotlinx-kover/tree/main/examples/android_kts
</details>

<details>
<summary>Groovy</summary>

`build.gradle` (Project)
```groovy
android {
// other Android declarations
testOptions {
unitTests.all {
if (name == "testDebugUnitTest") {
kover {
disabled = false // true to disable instrumentation tests of this task, Kover reports will not depend on the results of their execution
binaryReportFile.set(file("$buildDir/custom/debug-report.bin")) // set file name of binary report
includes = ['com.example.*'] // see "Instrumentation inclusion rules" below
excludes = ['com.example.subpackage.*'] // see "Instrumentation exclusion rules" below
}
}
plugin {
// ...
id 'org.jetbrains.kotlinx.kover' version "0.6.0"
}
koverMerged {
enable()
filters {
classes {
excludes.add "*.databinding.*" // ViewBinding
}
}
}
```

`build.gradle` (Module)
```groovy
plugins {
// ...
id 'org.jetbrains.kotlinx.kover'
}
android {
// ...
}
dependencies {
// ...
}
kover {
instrumentation {
excludeTasks.add "testReleaseUnitTest"
}
}
```

An example is available here: https://github.com/Kotlin/kotlinx-kover/tree/main/examples/android_groovy
</details>


Expand Down
1 change: 1 addition & 0 deletions examples/android_groovy/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
local.properties
1 change: 1 addition & 0 deletions examples/android_groovy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
To use Kover in an Android Project, run `./gradlew koverMergedHtmlReport`
68 changes: 68 additions & 0 deletions examples/android_groovy/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'org.jetbrains.kotlinx.kover'
}

android {
compileSdk 32

defaultConfig {
applicationId "org.jetbrains.kover_android_groovy_example"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildFeatures {
viewBinding true
}

buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = '1.8'
}

testOptions {
unitTests {
returnDefaultValues = true
}
}
}

dependencies {

implementation 'androidx.core:core-ktx:1.8.0'
implementation "androidx.fragment:fragment-ktx:1.5.2"
implementation 'androidx.appcompat:appcompat:1.5.0'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

// Lifecycle
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"

testImplementation 'junit:junit:4.13.2'
testImplementation 'androidx.arch.core:core-testing:2.1.0'
testImplementation "io.mockk:mockk:1.12.7"
}

kover {
instrumentation {
excludeTasks.add "testReleaseUnitTest"
}
}
27 changes: 27 additions & 0 deletions examples/android_groovy/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.jetbrains.kover_android_groovy_example"
>

<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.KoverExample"
>
<activity
android:name=".MainActivity"
android:exported="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.jetbrains.kover_android_groovy_example

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.ViewModelProvider
import org.jetbrains.kover_android_groovy_example.databinding.MainActivityBinding

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val binding = MainActivityBinding.inflate(layoutInflater)

setContentView(binding.root)

val viewModel = ViewModelProvider(this, ViewModelFactory)[MainViewModel::class.java]

binding.mainEditTextName.addTextChangedListener {
viewModel.onUserNameChanged(it?.toString())
}

viewModel.messageLiveData.observe(this) {
binding.mainTextViewMessage.text = it
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.jetbrains.kover_android_groovy_example

import androidx.lifecycle.Transformations
import androidx.lifecycle.ViewModel

class MainViewModel(private val userRepository: UserRepository) : ViewModel() {

val messageLiveData = Transformations.map(userRepository.userNameLiveData) {
"Hello, $it!"
}

fun onUserNameChanged(userName: String?) {
if (userName != null) {
userRepository.setUserName(userName)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.jetbrains.kover_android_groovy_example

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData

class UserRepository {

private val _userNameMutableLiveData = MutableLiveData<String>()
val userNameLiveData: LiveData<String> = _userNameMutableLiveData

fun setUserName(userName: String) {
_userNameMutableLiveData.value = userName
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.jetbrains.kover_android_groovy_example

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider

object ViewModelFactory : ViewModelProvider.Factory {

private val userRepository = UserRepository()

@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T = when {
modelClass.isAssignableFrom(MainViewModel::class.java) -> MainViewModel(userRepository)
else -> throw IllegalArgumentException("Unknown ViewModel class: $modelClass")
} as T
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108"
>
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear"
>
<item
android:color="#44000000"
android:offset="0.0"
/>
<item
android:color="#00000000"
android:offset="1.0"
/>
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000"
/>
</vector>

0 comments on commit 562d11c

Please sign in to comment.