https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
j

José González Gómez

05/03/2021, 11:35 AM
Can you use shared resources for tests in a Kotlin Multiplatform Mobile project? I tried to include some JSON files under
src/commonTest/resources
but they don't seem to get copied to the output directory when running Android tests. Putting them under
src/androidTest/resources
did the trick for Android tests, but I don't want to have two copies of these files, as they are common for both Android and iOS tests.
👀 2
d

Derek Ellis

05/03/2021, 11:47 AM
I wrote this to make use of test resources in common tests: https://gist.github.com/dellisd/a1df42787d42b41cd3ce16f573984674 It reads them from the
commonTest/resources
directory, but in a lot of cases that's good enough.
j

José González Gómez

05/03/2021, 12:00 PM
thanks!
n

Nicolas Verinaud

05/03/2021, 12:19 PM
Creating symbolic links might also do the trick. 🙂
j

José González Gómez

05/03/2021, 12:43 PM
🤔 I'm afraid we've got too many Windows machines hanging around for Android development...
m

Michal Klimczak

05/03/2021, 2:31 PM
Oh, I was just wondering about the same thing yesterday, but I don't have idea how to approach this with iosTest target. https://kotlinlang.slack.com/archives/C3SGXARS6/p1620045905289200?thread_ts=1620045905.289200&cid=C3SGXARS6
I just had a massive ide issue around using
androidTest/resources
. In case anyone has the same: https://kotlinlang.slack.com/archives/C3PQML5NU/p1620201399394700?thread_ts=1620195839.390000&cid=C3PQML5NU
j

José González Gómez

05/05/2021, 10:28 AM
Ok, I finally managed to do it, although there are some cases that still don't work... I put the shared test resources under
commonTest/resources
, and then add the following snippet in the shared project's `build.gradle.kts`:
Copy code
afterEvaluate {
    listOf("debug", "release").forEach { variant ->
        val copyTaskName = "copyResources${variant.capitalize()}UnitTest"
        tasks.register<Copy>(copyTaskName) {
            from("$projectDir/src/commonTest/resources")
            into("$buildDir/tmp/kotlin-classes/${variant}UnitTest/")
        }
        tasks.getByName("test${variant.capitalize()}UnitTest") {
            dependsOn(copyTaskName)
        }
    }

    tasks.register<Copy>("copyResourcesIosX64DebugTest") {
        from("$projectDir/src/commonTest/resources")
        into("$buildDir/bin/iosX64/debugTest/")
    }
    tasks.getByName("iosX64Test") {
        dependsOn("copyResourcesIosX64DebugTest")
    }
}
and then I have a `expect`/`actual` class to load resources:
Copy code
expect class TestResource(path: String) {
    val content: String?
}

actual class TestResource actual constructor(path: String) {
    actual val content: String? = NSString.stringWithContentsOfFile(NSBundle.mainBundle.pathForResource(path, null)!!) as String?
}

actual class TestResource actual constructor(path: String) {
    actual val content: String? = this::class.java.classLoader?.getResource(path)?.readText()
}
Be careful! The
into
directories seem to change depending on the Android Studio / Gradle version
Maybe somebody with more Gradle experience than me can help with this... with this solution the first time I execute
./gradlew testDebugUnitTest
after a
./gradlew clean
the build fails because the files aren't copied to the destination. The second time the files are copied and the build is successful. I thought that maybe the copy task doesn't create the target directory, so I tried to manually create it before executing the tests, but this didn't work
found the culprit, the Kotlin compilation deletes the destination directory, so the copy task must be run after them:
Copy code
// Top of build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

// Inside the task definition
        tasks.register<Copy>(copyTaskName) {
            ...
            mustRunAfter(tasks.withType<KotlinCompile>())
        }
g

goncalossilva

12/13/2021, 2:53 PM
Inspired by this discussion (and @Derek Ellis’s gist!), I’ve open-sourced goncalossilva/kotlinx-resources 🙂
K 3
❤️ 1
212 Views