I havee to admit, it's very frustrating that there...
# multiplatform
d
I havee to admit, it's very frustrating that there is no standard template or set of examples for KMP online. The wizard I used to create my project, I can't find an example anywhere that uses a similar gradle setup, so am having a hard time adding Android unit tests to the project. In the sourceSets {} part of the composeApp/build.gradle.kts file, how does one add dependencies to create unit tests? My project's code is here: https://github.com/comixed/variant/tree/master
j
Android unit tests go in the androidUnitTest source set.
d
@Jeff Lockhart But just dropping files there isn't enough: there are dependencies that need to be added, but I can't find anything that shows what to do.
For example, I added a file to test a composable, and it says it can't find "createComposeRule()".
j
Dependencies can be added like to any other source set. Kotlin 1.9.20 adds type-safe accessors for the default source sets as well.
Copy code
kotlin {
    sourceSets {
        androidUnitTest.dependencies {
            implementation(...)
        }
    }
}
d
Hrm, adding the above, I'm getting "Unresolved reference: androidUnitTest".
I'm just very lost and have no idea how to get this working. As I mentioned before, every project I look at, the Gradle files are all over the place different from each other. It's very confusing to know what to do.
j
You can get any source set using either of these methods, if a type-safe accessor isn't available:
Copy code
kotlin {
    sourceSets {
        named("androidUnitTest").dependencies {
            implementation(...)
        }
        val androidUnitTest by getting {
            dependencies {
                implementation(...)
            }
        }
    }
}
d
Understood. What about setting the runner for unit tests? Any suggestions for how to fix that?
j
You can configure Android in a KMP project the same way you configure it in a plain Android project, using the Android Gradle plugin configuration block. For example:
Copy code
android {
    compileSdk = 34
    defaultConfig {
        minSdk = 22
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}
d
I've applied that change, but still am getting the same result; i.e., running the unit test results in a thrown "FINGERPRINT must not be null" NPE. Googling that, it means the unit test isn't running using the Android instrumentation, but Java. I'm just very lost in the weeds here with getting Compose tests running.
Would you mind looking at the branch and giving me some advice? https://github.com/mcpierce/variant/tree/feature/issue-35
j
That's because the androidUnitTest source set is for running Android unit tests on the JVM. The androidInstrumentedTest source set is for running instrumented tests. By default androidUnitTest is connected to the commonTest source tree and the androidInstrumentedTest source set is not. You can switch this so your androidInstrumentedTests are in the commonTest source set tree instead of androidUnitTest:
Copy code
kotlin {
    @OptIn(ExperimentalKotlinGradlePluginApi::class)
    androidTarget {
        instrumentedTestVariant.sourceSetTree.set(KotlinSourceSetTree.test)
        unitTestVariant.sourceSetTree.set(KotlinSourceSetTree.unitTest)
    }
}
I'm doing this in my library here.
d
kk, so I should rename androidUnitTest => androidInstrumentedTest, yeah? Sorry if I'm coming across as obtuse here. Will that then be able to run tests on @Compose functions? That's what I'm trying to do right now.
j
Yes, if the code in that source set is intended to be run as an Android instrumented test.
👍 2
d
I'm making progress, but guess I still have some missing dependencies. The test appears to be trying to run on an Android instrument, but is failing when doing the composable:
j
Did you assign the androidInstrumentedTest source set to the commonTest tree, like I described above? It looks as if it's not getting the test dependencies from commonTest. Is it your intention to be using Compose Multiplatform? Because it appears you are just using Compose for Android. Is it your intention to only target Android? You're adding dependencies for the iOS source set, but you're not declaring any iOS targets, as the compiler is warning. You mention desktop in your readme, but you're also not declaring the JVM target either.
d
I just renamed that entry in the gradle file before you replied, realizing it should match what's in the file system. The test now fails with a RuntimeException "Intent in process org.comixedproject.variant resolved to different process org.comixedproject.variant.test: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10008000 cmp=org.comixedproject.variant.test/androidx.activity.ComponentActivity }" Our current goals for the project now are: 1) Android UX will using Compose, 2) iOS UX will use Swift, 3) both will share as much backend code as possible. At some point in future we may bring both UX together into a single Compose Multiplatform, but that won't be till that's out of Alpha and is stable.
Also, the initial platform is Android, but I'm going to experiment with iOS during development. If I can put them both out at the same time, great, but Android is the primary target for our MVP.
👍 2
@Jeff Lockhart If you could, please reload the link I shared previously: I've pushed my changes on that branch up so you could see what I've done. You've been very help, and I feel like I'm on the cusp of getting this first test running and enabling me to add the composable tests for the project.
j
I don't know what's causing the error you're still seeing. It seems to have something to do with the compose test rule.
d
@Jeff Lockhart If you can point me to a project somewhere that's using KMP and has Compose testing, I'd appreciate it. I'll do the deep dive to learn the differences.
j
I don't know of a specific example project that does this. I would try asking about the error in #compose-android to see if anyone there might have seen this before. You might also consider using Compose Multiplatform instead of Android's Compose UI and see if this will work better. It would give you the ability to use your UI code for desktop and potentially iOS as well.
d
I appreciate the recommendation. At this time, though, we want to do the UX for iOS using Swift, since CMP isn't past the alpha stage.
j
You could still use SwiftUI for iOS with CMP code used for Android and desktop, which are both stable. Only iOS CMP is in alpha.