chrmelchior
05/25/2023, 1:57 PMkotlin {
sourceSets {
val commonMain by getting {
dependencies {
// This will pull in library-base-android for both
// Android Unit Test and Instrumented Tests
implementation("io.realm.kotlin:library-base:1.10.0-SNAPSHOT")
}
}
val androidUnitTest by getting {
dependencies {
// Here I need to override the library-base-android variant
// with the library-base-jvm dependency.
}
}
val androidInstrumentedTest by getting {
dependencies {
// This should continue to use the library-base-android variant.
}
}
}
}
Anyone have any idea on how to achieve this? 🤔
Can I make a release of the library with some metadata for the source set resolution to “just work” or is there some way to manipulate the Gradle depedency inside the the two different test closures?Jeff Lockhart
05/25/2023, 5:10 PMandroidInstrumentedTest
and androidUnitTest
source sets should be added to: https://kotlinlang.slack.com/archives/C3PQML5NU/p1682443478051419?thread_ts=1675016886.869689&cid=C3PQML5NU
Note the API has been updated slightly since this post. You now call it directly from the androidTarget()
declaration (which replaces the previous android()
target declaration):
androidTarget {
publishLibraryVariants("release")
instrumentedTestVariant.sourceSetTree.set(SourceSetTree.test)
unitTestVariant.sourceSetTree.set(SourceSetTree.unitTest)
}
You can check it out in the latest 1.9.0-Beta release: https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev/androidUnitTest
, if you're supporting the JVM target as well, I'd just use the jvmTest
source set to run those tests and omit the androidUnitTest
by assigning it to the unitTest
source set tree as my code above does. This is what I'm doing in my library.chrmelchior
05/25/2023, 5:45 PMandroid.os.Build
(which is not available in the unit test variant), but our users shouldn’t care about that. We also load some native code, which behaves very different on Android devices vs. JVM.
All of those things are kinda hidden for people right now because they just interact with the Multiplatform API, and it “just works” because the variant metadata allows Gradle to select the proper dependency based on the projet type.
But the androidUnitTest is some sort of hybrid between Jvm and Android which makes it hard for libraries to handle (as far as I can tell).
Not sure if that made sense?Jeff Lockhart
05/25/2023, 5:58 PMandroidUnitTest
source set? Or just commonTest
?android
or jvm
variant, depending on their use case, right?As I understand the new API it “just” allows decoupling of unit tests from instrumentation tests?I don't know that I'd call it decoupling these test source sets. They have always been their own separate source sets, but a sort of anomaly as they don't fit with the regular KMP source set layout (main + test). This API now gives control over which source set tree each Android test source set inherits from. In Kotlin <=1.7, both unit and instrumented tests inherited from the
commonTest
source set tree. In 1.8, the androidInstrumentedTest
source set was decoupled from this tree by default (you can recouple it with a dependsOn
call), but there was no way to remove the dependsOn
relationship for the androidUnitTest
source set. So this API provides the ability to configure both androidInsturmentedTest
and androidUnitTest
to belong to whichever source set tree makes sense for your code.androidUnitTest
source set? And how do your library users depend on your tests?
we want to allow users of our library to run tests on either JVM or Android as they see fitDo you mean consumers of your library being able to run their own tests as either JVM or Android instrumented or unit tests? Because they should be able to do this depending on the
jvm
or android
publications of your library, right?chrmelchior
05/25/2023, 6:31 PMandroid
or jvm
publications we publish. The multiplatform plugin selects the right one automatically and pure android projects use the -android
artifact directly.
I suspect we need to do some gradle dependency substitution for pure android projects no matter what, but for multiplatform projects it would be nice if we could either release some artifact that androidUniTest
would automatically pick or modify the gradle metadata some the jvm
publication was chosen by androidUnitTest
rather than the android
publication.Jeff Lockhart
05/25/2023, 6:36 PMandroidUnitTest
or are you just running commonTest
tests?androidUnitTest
, what platform Gradle would select on in this case. KMP publishes attributes on the platform variants. But will gradle choose android
or standard-jvm
for the org.gradle.jvm.environment
attribute? There's also the org.jetbrains.kotlin.platform.type
attribute with jvm
and androidJvm
.chrmelchior
05/25/2023, 6:41 PMandroidUnitTests
that only was available on Android. In that case they would go to the androidInstrumentedTest
folderJeff Lockhart
05/25/2023, 6:47 PMjvm
attribute variant, I'd expect you should be able to declare the base artifact:
dependencies {
implementation("lib")
}
And it would choose the -android
variant for the main build and instrumented tests automatically, and then choose the -jvm
variant for unit tests, if it does work this way.
You could manually declare the variant for the unit tests:
dependencies {
implementation("lib-android")
testImplementation("lib-jvm")
}
In this case, it's forcing both onto the classpath and it should exclude the variant that doesn't match the platform attribute. If that's jvm
for Android unit tests, then it should work as expected, just not sure if that's the case or not.
(You should be able to do this similarly with multiplatform dependency declaration.)chrmelchior
05/25/2023, 6:49 PMandroidUnitTest
is a mix of both Android and JVMJeff Lockhart
05/25/2023, 6:51 PMBut ideally we want to move to a world where all the common tests are actually in “commonTest” and then each platform has its own.
So there wouldn’t beThis sounds like you'd then be able to do what I described initially, removingthat only was available on Android. In that case they would go to theandroidUnitTests
folderandroidInstrumentedTest
androidUnitTest
from and adding androidInstrumentedTest
to SourceSetTree.test
.jvm
variant's platform attribute to be android
and the android
variant's attribute jvm
, specifically for the androidUniTest
source set. But that would be pretty hacky.chrmelchior
05/25/2023, 7:53 PMJeff Lockhart
05/25/2023, 7:56 PMorg.gradle.jvm.environment
and org.jetbrains.kotlin.platform.type
attributes that a source set selects variants on.chrmelchior
05/26/2023, 8:08 AMconfigurations.all {
// Ensure that androidUnitTest uses the Realm JVM variant rather than Android.
if (name == "debugUnitTestRuntimeClasspath") {
resolutionStrategy.dependencySubstitution {
substitute(module("io.realm.kotlin:library-base:${Realm.version}")).using(
module("io.realm.kotlin:library-base-jvm:${Realm.version}")
)
substitute(module("io.realm.kotlin:cinterop:${Realm.version}")).using(
module("io.realm.kotlin:cinterop-jvm:${Realm.version}")
)
}
}
}
And that will work fine for our internal tests, but is going to be pretty annoying for our external users. I’ll try to ask in #gradle and see if they have a better idea. Thanks for the hints 🙏Jeff Lockhart
05/26/2023, 3:21 PMchrmelchior
05/26/2023, 3:36 PM