From 5be4448787c27d6a7271a95a90686c1ee55ce6bb Mon Sep 17 00:00:00 2001 From: Petrus Nguyen Thai Hoc Date: Mon, 16 Aug 2021 00:32:02 +0700 Subject: [PATCH 01/17] add stuff --- buildSrc/src/main/kotlin/deps.kt | 4 + feature-main/build.gradle.kts | 11 ++ .../java/com/hoc/flowmvi/ui/main/MainVM.kt | 84 ++++++------- .../com/hoc/flowmvi/ui/ExampleUnitTest.kt | 15 --- .../com/hoc/flowmvi/ui/main/MainVMTest.kt | 110 ++++++++++++++++++ 5 files changed, 169 insertions(+), 55 deletions(-) delete mode 100644 feature-main/src/test/java/com/hoc/flowmvi/ui/ExampleUnitTest.kt create mode 100644 feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt diff --git a/buildSrc/src/main/kotlin/deps.kt b/buildSrc/src/main/kotlin/deps.kt index 96b9d0f2..b024d950 100644 --- a/buildSrc/src/main/kotlin/deps.kt +++ b/buildSrc/src/main/kotlin/deps.kt @@ -51,6 +51,7 @@ object deps { const val core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version" const val android = "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version" + const val test = "org.jetbrains.kotlinx:kotlinx-coroutines-test:$version" } object koin { @@ -68,6 +69,9 @@ object deps { const val junit = "junit:junit:4.13" const val androidxJunit = "androidx.test.ext:junit:1.1.2" const val androidXSspresso = "androidx.test.espresso:espresso-core:3.3.0" + + const val mockk = "io.mockk:mockk:1.12.0" + const val kotlinJUnit = "org.jetbrains.kotlin:kotlin-test-junit:$kotlinVersion" } } diff --git a/feature-main/build.gradle.kts b/feature-main/build.gradle.kts index 83ea61ed..c4d9b159 100644 --- a/feature-main/build.gradle.kts +++ b/feature-main/build.gradle.kts @@ -31,6 +31,13 @@ android { kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString() } buildFeatures { viewBinding = true } + + testOptions { + unitTests { + isReturnDefaultValues = true + isIncludeAndroidResources = true + } + } } dependencies { @@ -53,4 +60,8 @@ dependencies { implementation(deps.coil) implementation(deps.viewBindingDelegate) implementation(deps.flowExt) + + testImplementation(deps.test.mockk) + testImplementation(deps.test.kotlinJUnit) + testImplementation(deps.coroutines.test) } diff --git a/feature-main/src/main/java/com/hoc/flowmvi/ui/main/MainVM.kt b/feature-main/src/main/java/com/hoc/flowmvi/ui/main/MainVM.kt index 09599d55..b8d092f4 100644 --- a/feature-main/src/main/java/com/hoc/flowmvi/ui/main/MainVM.kt +++ b/feature-main/src/main/java/com/hoc/flowmvi/ui/main/MainVM.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.emitAll import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.filterNot @@ -85,49 +86,52 @@ internal class MainVM( } } - private fun Flow.toPartialChangeFlow(): Flow = shareIn(viewModelScope, SharingStarted.WhileSubscribed()).run { - val getUserChanges = getUsersUseCase() - .onEach { Log.d("###", "[MAIN_VM] Emit users.size=${it.size}") } - .map { - val items = it.map(::UserItem) - PartialChange.GetUser.Data(items) as PartialChange.GetUser - } - .onStart { emit(PartialChange.GetUser.Loading) } - .catch { emit(PartialChange.GetUser.Error(it)) } + private fun Flow.toPartialChangeFlow(): Flow = + shareIn(viewModelScope, SharingStarted.WhileSubscribed()).run { + val getUserChanges = defer(getUsersUseCase::invoke) + .onEach { Log.d("###", "[MAIN_VM] Emit users.size=${it.size}") } + .map { + val items = it.map(::UserItem) + PartialChange.GetUser.Data(items) as PartialChange.GetUser + } + .onStart { emit(PartialChange.GetUser.Loading) } + .catch { emit(PartialChange.GetUser.Error(it)) } - val refreshChanges = refreshGetUsers::invoke - .asFlow() - .map { PartialChange.Refresh.Success as PartialChange.Refresh } - .onStart { emit(PartialChange.Refresh.Loading) } - .catch { emit(PartialChange.Refresh.Failure(it)) } + val refreshChanges = refreshGetUsers::invoke + .asFlow() + .map { PartialChange.Refresh.Success as PartialChange.Refresh } + .onStart { emit(PartialChange.Refresh.Loading) } + .catch { emit(PartialChange.Refresh.Failure(it)) } - return merge( - filterIsInstance() - .logIntent() - .flatMapConcat { getUserChanges }, - filterIsInstance() - .filter { viewState.value.let { !it.isLoading && it.error === null } } - .logIntent() - .flatMapFirst { refreshChanges }, - filterIsInstance() - .filter { viewState.value.error != null } - .logIntent() - .flatMapFirst { getUserChanges }, - filterIsInstance() - .logIntent() - .map { it.user } - .flatMapMerge { userItem -> - flow { - userItem - .toDomain() - .let { removeUser(it) } - .let { emit(it) } + return merge( + filterIsInstance() + .logIntent() + .flatMapConcat { getUserChanges }, + filterIsInstance() + .filter { viewState.value.let { !it.isLoading && it.error === null } } + .logIntent() + .flatMapFirst { refreshChanges }, + filterIsInstance() + .filter { viewState.value.error != null } + .logIntent() + .flatMapFirst { getUserChanges }, + filterIsInstance() + .logIntent() + .map { it.user } + .flatMapMerge { userItem -> + flow { + userItem + .toDomain() + .let { removeUser(it) } + .let { emit(it) } + } + .map { PartialChange.RemoveUser.Success(userItem) as PartialChange.RemoveUser } + .catch { emit(PartialChange.RemoveUser.Failure(userItem, it)) } } - .map { PartialChange.RemoveUser.Success(userItem) as PartialChange.RemoveUser } - .catch { emit(PartialChange.RemoveUser.Failure(userItem, it)) } - } - ) - } + ) + } private fun Flow.logIntent() = onEach { Log.d("MainVM", "## Intent: $it") } } + +private fun defer(flowFactory: () -> Flow): Flow = flow { emitAll(flowFactory()) } diff --git a/feature-main/src/test/java/com/hoc/flowmvi/ui/ExampleUnitTest.kt b/feature-main/src/test/java/com/hoc/flowmvi/ui/ExampleUnitTest.kt deleted file mode 100644 index bac2a27d..00000000 --- a/feature-main/src/test/java/com/hoc/flowmvi/ui/ExampleUnitTest.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.hoc.flowmvi.ui - -import org.junit.Test - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} diff --git a/feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt b/feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt new file mode 100644 index 00000000..162eba15 --- /dev/null +++ b/feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt @@ -0,0 +1,110 @@ +package com.hoc.flowmvi.ui.main + +import com.hoc.flowmvi.domain.entity.User +import com.hoc.flowmvi.domain.usecase.GetUsersUseCase +import com.hoc.flowmvi.domain.usecase.RefreshGetUsersUseCase +import com.hoc.flowmvi.domain.usecase.RemoveUserUseCase +import io.mockk.clearAllMocks +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.take +import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.TestCoroutineDispatcher +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.setMain +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertContentEquals + +val users = listOf( + User( + id = "1", + email = "email1@gmail.com", + firstName = "first1", + lastName = "last1", + avatar = "1.png" + ), + User( + id = "2", + email = "email1@gmail.com", + firstName = "first2", + lastName = "last2", + avatar = "2.png" + ), + User( + id = "3", + email = "email1@gmail.com", + firstName = "first3", + lastName = "last3", + avatar = "3.png" + ), +) + +internal val usersItems = users.map { UserItem(it) } + +@ExperimentalCoroutinesApi +@FlowPreview +class MainVMTest { + private val testDispatcher = TestCoroutineDispatcher() + + private lateinit var vm: MainVM + private val getUserUseCase: GetUsersUseCase = mockk(relaxed = true) + private val refreshGetUsersUseCase: RefreshGetUsersUseCase = mockk(relaxed = true) + private val removeUser: RemoveUserUseCase = mockk(relaxed = true) + + @BeforeTest + fun setup() { + Dispatchers.setMain(testDispatcher) + + vm = MainVM( + getUsersUseCase = getUserUseCase, + refreshGetUsers = refreshGetUsersUseCase, + removeUser = removeUser, + ) + } + + @AfterTest + fun teardown() { + Dispatchers.resetMain() + clearAllMocks() + } + + @Test + fun `ViewIntent_Initial returns success`() = testDispatcher.runBlockingTest { + every { getUserUseCase() } returns flow { + delay(100) + emit(users) + } + + launch(start = CoroutineStart.UNDISPATCHED) { + vm.viewState + .take(2) + .toList() + .let { + assertContentEquals( + it, + listOf( + ViewState.initial(), + ViewState( + userItems = usersItems, + isLoading = false, + error = null, + isRefreshing = false + ) + ) + ) + } + } + + vm.processIntent(ViewIntent.Initial) + } +} From c451c88fb6f1069311c9644b9e85d064abdc44c9 Mon Sep 17 00:00:00 2001 From: Petrus Nguyen Thai Hoc Date: Mon, 16 Aug 2021 00:39:35 +0700 Subject: [PATCH 02/17] add workflows --- .github/workflows/unit-test.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/unit-test.yml diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml new file mode 100644 index 00000000..d432d558 --- /dev/null +++ b/.github/workflows/unit-test.yml @@ -0,0 +1,25 @@ +name: Build CI + +on: + push: + branches: [ master, add-unit-test ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Set up JDK + uses: actions/setup-java@v2 + with: + distribution: 'zulu' + java-version: '11' + + - name: Make gradlew executable + run: chmod +x ./gradlew + + - name: Run Debug Unit Test + run: ./gradlew testDebugUnitTest --warning-mode all --stacktrace From 99e14e8cb990a87d299c10d77c3fecb7b320bd95 Mon Sep 17 00:00:00 2001 From: Petrus Nguyen Thai Hoc Date: Mon, 16 Aug 2021 02:51:43 +0700 Subject: [PATCH 03/17] add workflows --- .../java/com/hoc/flowmvi/data/ExampleUnitTest.kt | 14 -------------- .../java/com/hoc/flowmvi/ui/add/ExampleUnitTest.kt | 14 -------------- 2 files changed, 28 deletions(-) diff --git a/data/src/test/java/com/hoc/flowmvi/data/ExampleUnitTest.kt b/data/src/test/java/com/hoc/flowmvi/data/ExampleUnitTest.kt index f160a149..0841384b 100644 --- a/data/src/test/java/com/hoc/flowmvi/data/ExampleUnitTest.kt +++ b/data/src/test/java/com/hoc/flowmvi/data/ExampleUnitTest.kt @@ -1,15 +1 @@ package com.hoc.flowmvi.data - -import org.junit.Test - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} diff --git a/feature-add/src/test/java/com/hoc/flowmvi/ui/add/ExampleUnitTest.kt b/feature-add/src/test/java/com/hoc/flowmvi/ui/add/ExampleUnitTest.kt index 8b9356a7..ded25567 100644 --- a/feature-add/src/test/java/com/hoc/flowmvi/ui/add/ExampleUnitTest.kt +++ b/feature-add/src/test/java/com/hoc/flowmvi/ui/add/ExampleUnitTest.kt @@ -1,15 +1 @@ package com.hoc.flowmvi.ui.add - -import org.junit.Test - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} From 1f9bcf68c48c65f0c086639c5db1e8a7228b0cca Mon Sep 17 00:00:00 2001 From: Petrus Nguyen Thai Hoc Date: Mon, 16 Aug 2021 03:12:55 +0700 Subject: [PATCH 04/17] add `ViewIntent_Initial returns failure` --- .../com/hoc/flowmvi/ui/main/MainVMTest.kt | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt b/feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt index 162eba15..9a0d0c96 100644 --- a/feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt +++ b/feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt @@ -7,11 +7,13 @@ import com.hoc.flowmvi.domain.usecase.RemoveUserUseCase import io.mockk.clearAllMocks import io.mockk.every import io.mockk.mockk +import io.mockk.verify import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toList @@ -20,10 +22,15 @@ import kotlinx.coroutines.test.TestCoroutineDispatcher import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.runBlockingTest import kotlinx.coroutines.test.setMain +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicReference import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertContentEquals +import kotlin.test.assertEquals +import kotlin.test.assertFalse val users = listOf( User( @@ -85,6 +92,13 @@ class MainVMTest { emit(users) } + val hasEvent = AtomicBoolean(false) + val eventJob = launch(start = CoroutineStart.UNDISPATCHED) { + vm.singleEvent.collect { + hasEvent.set(true) + } + } + launch(start = CoroutineStart.UNDISPATCHED) { vm.viewState .take(2) @@ -103,6 +117,60 @@ class MainVMTest { ) ) } + + eventJob.cancel() + assertFalse(hasEvent.get()) + verify(exactly = 1) { getUserUseCase() } + } + + vm.processIntent(ViewIntent.Initial) + } + + @Test + fun `ViewIntent_Initial returns failure`() = testDispatcher.runBlockingTest { + val ioException = IOException() + + every { getUserUseCase() } returns flow { + delay(100) + throw ioException + } + + val events = AtomicReference(emptyList()) + val eventJob = launch(start = CoroutineStart.UNDISPATCHED) { + vm.singleEvent.collect { e -> + events.updateAndGet { it + e } + } + } + + launch(start = CoroutineStart.UNDISPATCHED) { + vm.viewState + .take(2) + .toList() + .let { + assertContentEquals( + it, + listOf( + ViewState.initial(), + ViewState( + userItems = emptyList(), + isLoading = false, + error = ioException, + isRefreshing = false + ) + ) + ) + } + + eventJob.cancel() + + assertEquals( + events.get().single(), + SingleEvent.GetUsersError( + error = ioException, + ), + ) + + verify(exactly = 1) { getUserUseCase() } } vm.processIntent(ViewIntent.Initial) From 630c3391f546086611f42fb8acf2464ba1ee518f Mon Sep 17 00:00:00 2001 From: Petrus Nguyen Thai Hoc Date: Mon, 16 Aug 2021 04:07:44 +0700 Subject: [PATCH 05/17] jacoco --- .github/workflows/unit-test.yml | 35 +++++++++++++++++++++++--------- app/build.gradle.kts | 6 ++++++ build.gradle.kts | 1 + coverage.gradle.kts | 36 +++++++++++++++++++++++++++++++++ feature-main/build.gradle.kts | 4 ++++ 5 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 coverage.gradle.kts diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index d432d558..f0cbe054 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -10,16 +10,31 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - - name: Set up JDK - uses: actions/setup-java@v2 - with: - distribution: 'zulu' - java-version: '11' + - name: Set up JDK + uses: actions/setup-java@v2 + with: + distribution: 'zulu' + java-version: '11' - - name: Make gradlew executable - run: chmod +x ./gradlew + - name: Make gradlew executable + run: chmod +x ./gradlew - - name: Run Debug Unit Test - run: ./gradlew testDebugUnitTest --warning-mode all --stacktrace + - name: Run Debug Unit Test + run: ./gradlew testDebugUnitTest --warning-mode all --stacktrace + + - name: Upload Test Report + uses: actions/upload-artifact@v2 + with: + name: report + path: app/build/reports/jacoco/test/ + + - name: Download Test Reports Folder + uses: actions/download-artifact@v2 + with: + name: report + path: app/build/reports/jacoco/test/ + + - name: Upload Test Report + run: bash <(curl -s https://codecov.io/bash) -f "app/build/reports/jacoco/test/jacocoTestReport.xml" diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 822eb9d1..2dbb6a01 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,7 +1,9 @@ plugins { androidApplication kotlinAndroid + jacoco } +apply(from = "$rootDir/coverage.gradle.kts") android { compileSdk = appConfig.compileSdkVersion @@ -26,6 +28,10 @@ android { "proguard-rules.pro" ) } + + getByName("debug") { + isTestCoverageEnabled = true + } } compileOptions { diff --git a/build.gradle.kts b/build.gradle.kts index a56d167c..d4206612 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,6 +13,7 @@ buildscript { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") classpath("com.diffplug.spotless:spotless-plugin-gradle:5.14.2") classpath("dev.ahmedmourad.nocopy:nocopy-gradle-plugin:1.4.0") + classpath("org.jacoco:org.jacoco.core:0.8.3") } } diff --git a/coverage.gradle.kts b/coverage.gradle.kts new file mode 100644 index 00000000..07ddc156 --- /dev/null +++ b/coverage.gradle.kts @@ -0,0 +1,36 @@ +apply(plugin = "jacoco") + +tasks { + val debugCoverageReport by registering(JacocoReport::class) + debugCoverageReport { + dependsOn("testDebugUnitTest", "connectedDebugAndroidTest") + + reports { + xml.run { + required.value(true) + outputLocation.set(file("$buildDir/reports/jacoco/test/jacocoTestReport.xml")) + } + html.required.value(true) + } + + val kotlinClasses = fileTree("$buildDir/tmp/kotlin-classes/debug") + val coverageSourceDirs = arrayOf( + "src/main/java", + "src/debug/java" + ) + val executionDataDirs = fileTree("$buildDir") { + setIncludes( + listOf( + "jacoco/testDebugUnitTest.exec", + "outputs/code_coverage/debugAndroidTest/connected/*.ec", + "outputs/code-coverage/connected/*coverage.ec" + ) + ) + } + + classDirectories.setFrom(files(kotlinClasses)) + sourceDirectories.setFrom(coverageSourceDirs) + additionalSourceDirs.setFrom(files(coverageSourceDirs)) + executionData.setFrom(executionDataDirs) + } +} diff --git a/feature-main/build.gradle.kts b/feature-main/build.gradle.kts index c4d9b159..6705b0ef 100644 --- a/feature-main/build.gradle.kts +++ b/feature-main/build.gradle.kts @@ -22,6 +22,10 @@ android { "proguard-rules.pro" ) } + + getByName("debug") { + isTestCoverageEnabled = true + } } compileOptions { From 446346a79b793f1ff0e5b92a317db1fc435fb0c8 Mon Sep 17 00:00:00 2001 From: Petrus Nguyen Thai Hoc Date: Sun, 26 Sep 2021 21:57:26 +0700 Subject: [PATCH 06/17] wip --- .github/workflows/unit-test.yml | 2 +- app/build.gradle.kts | 6 +++++- build.gradle.kts | 13 ++++++++++++- buildSrc/src/main/kotlin/deps.kt | 7 +++++++ coverage.gradle.kts | 2 +- domain/build.gradle.kts | 2 ++ .../test/java/com/hoc/flowmvi/domain/ExampleTest.kt | 11 +++++++++++ feature-main/build.gradle.kts | 4 +--- 8 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 domain/src/test/java/com/hoc/flowmvi/domain/ExampleTest.kt diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index f0cbe054..cbfa000e 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -1,4 +1,4 @@ -name: Build CI +name: Unit Tests CI on: push: diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2dbb6a01..0be0c1f8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -3,7 +3,6 @@ plugins { kotlinAndroid jacoco } -apply(from = "$rootDir/coverage.gradle.kts") android { compileSdk = appConfig.compileSdkVersion @@ -40,6 +39,11 @@ android { } kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString() } buildFeatures { viewBinding = true } + + testOptions { + unitTests.isIncludeAndroidResources = true + unitTests.isReturnDefaultValues = true + } } dependencies { diff --git a/build.gradle.kts b/build.gradle.kts index d4206612..47cfe332 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,18 +7,21 @@ buildscript { google() mavenCentral() gradlePluginPortal() + maven(url = "https://oss.sonatype.org/content/repositories/snapshots") } dependencies { classpath("com.android.tools.build:gradle:7.0.0") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") classpath("com.diffplug.spotless:spotless-plugin-gradle:5.14.2") classpath("dev.ahmedmourad.nocopy:nocopy-gradle-plugin:1.4.0") - classpath("org.jacoco:org.jacoco.core:0.8.3") + classpath("com.vanniktech:gradle-android-junit-jacoco-plugin:0.17.0-SNAPSHOT") } } subprojects { + tasks.withType { useJUnitPlatform() } apply(plugin = "com.diffplug.spotless") + apply(plugin = "com.vanniktech.android.junit.jacoco") configure { kotlin { @@ -60,6 +63,14 @@ subprojects { endWithNewline() } } + + configure { + jacocoVersion = "0.8.3" + includeNoLocationClasses = true + csv.isEnabled = false + xml.isEnabled = true + html.isEnabled = true + } } allprojects { diff --git a/buildSrc/src/main/kotlin/deps.kt b/buildSrc/src/main/kotlin/deps.kt index b024d950..c107d095 100644 --- a/buildSrc/src/main/kotlin/deps.kt +++ b/buildSrc/src/main/kotlin/deps.kt @@ -1,6 +1,7 @@ @file:Suppress("unused", "ClassName", "SpellCheckingInspection") import org.gradle.api.artifacts.dsl.DependencyHandler +import org.gradle.kotlin.dsl.DependencyHandlerScope import org.gradle.kotlin.dsl.project import org.gradle.plugin.use.PluginDependenciesSpec import org.gradle.plugin.use.PluginDependencySpec @@ -89,3 +90,9 @@ inline val DependencyHandler.data get() = project(":data") inline val DependencyHandler.featureMain get() = project(":feature-main") inline val DependencyHandler.featureAdd get() = project(":feature-add") inline val DependencyHandler.featureSearch get() = project(":feature-search") + +fun DependencyHandler.addUnitTest() { + add("testImplementation", deps.test.mockk) + add("testImplementation", deps.test.kotlinJUnit) + add("testImplementation", deps.coroutines.test) +} diff --git a/coverage.gradle.kts b/coverage.gradle.kts index 07ddc156..aa6b4a14 100644 --- a/coverage.gradle.kts +++ b/coverage.gradle.kts @@ -3,7 +3,7 @@ apply(plugin = "jacoco") tasks { val debugCoverageReport by registering(JacocoReport::class) debugCoverageReport { - dependsOn("testDebugUnitTest", "connectedDebugAndroidTest") + dependsOn("testDebugUnitTest") reports { xml.run { diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index 45c82b6d..70551289 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -5,4 +5,6 @@ plugins { dependencies { implementation(deps.coroutines.core) implementation(deps.koin.core) + + addUnitTest() } diff --git a/domain/src/test/java/com/hoc/flowmvi/domain/ExampleTest.kt b/domain/src/test/java/com/hoc/flowmvi/domain/ExampleTest.kt new file mode 100644 index 00000000..7ae3f4f7 --- /dev/null +++ b/domain/src/test/java/com/hoc/flowmvi/domain/ExampleTest.kt @@ -0,0 +1,11 @@ +package com.hoc.flowmvi.domain + +import kotlin.test.Test +import kotlin.test.assertEquals + +class ExampleTest { + @Test + fun example() { + assertEquals(1, 1) + } +} diff --git a/feature-main/build.gradle.kts b/feature-main/build.gradle.kts index 6705b0ef..56195a4c 100644 --- a/feature-main/build.gradle.kts +++ b/feature-main/build.gradle.kts @@ -65,7 +65,5 @@ dependencies { implementation(deps.viewBindingDelegate) implementation(deps.flowExt) - testImplementation(deps.test.mockk) - testImplementation(deps.test.kotlinJUnit) - testImplementation(deps.coroutines.test) + addUnitTest() } From 218a9e843454ccd91a0212d5d5e2c70ec5c99093 Mon Sep 17 00:00:00 2001 From: Petrus Nguyen Thai Hoc Date: Mon, 4 Oct 2021 15:06:12 +0700 Subject: [PATCH 07/17] fix wip failed --- .idea/compiler.xml | 2 +- .idea/gradle.xml | 2 +- .idea/misc.xml | 2 +- build.gradle.kts | 15 ++++++++++++++- buildSrc/src/main/kotlin/deps.kt | 5 +++-- .../java/com/hoc/flowmvi/ui/main/MainVMTest.kt | 1 + 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 7e7ee626..fb7f4a8a 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index c22de178..a848f091 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -7,7 +7,7 @@