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

jw

06/03/2021, 2:29 AM
is it possible to exclude files from commonTest from being compiled as part of, say, jsTest? I tried the naive thing of adding
jsTest { kotlin { exclude '..' } }
but it seems to have no effect. my current workaround is to eliminate the commonTest srcDir and add it as a srcDir to each platform-specific target's test source set and then do the exclude
4
l

louiscad

06/03/2021, 2:55 AM
I think the only way that will work without bending the tools is making a funnily named sourceSet like
allButJsTest
and make all platform specific test sourceSets but the js one depend on it in the Gradle DSL.
j

jw

06/03/2021, 3:01 AM
each platform excludes a different subset so that would be exponential
l

louiscad

06/03/2021, 3:04 AM
Up to a certain limit, right? I think with the right logic (and that might be a place where the Kotlin DSL shines for those not familiar with Groovy), you can make the sourceSets generation and exclusion relatively easily. Can you give a second example of an exclude you also want, so that I can ensure I undertood correctly?
j

jw

06/03/2021, 3:06 AM
native excludes a different subset and android excludes a different subset
l

louiscad

06/03/2021, 3:09 AM
The excluded subset is just one, or more than one target?
j

jw

06/03/2021, 3:10 AM
imagine the common sourceset contains 20 files 1.kt, 2.kt, etc. js excludes everything divisible by 2, native everything by 3, and android everything by 4. JVM runs everything.
and sadly the real rules of exclusion are completely arbitrary files that only work in certain places. my effort is probably better spent fixing them to work in more places than creating elaborate exclusion mechanisms.
l

louiscad

06/03/2021, 3:17 AM
Looks like you'll need to pick coming up with a developer meaningful sourceSets naming (regarding what sets the tests abilities to run on a given set of platform or being excluded from it), or making the code, test or not, work on all these platforms, yes. The division thing felt like a puzzle BTW 😅
t

Tijl

06/04/2021, 8:31 AM
I think the excludes don’t work because
jsTest
has a preconfigured
dependsOn
commonTest
, and the filtering only applies on the sourceSet itself, so
jsTest
and not the sourceSets it depends on (
commonTest
) Rather than adding a srcDir to a platform set you could make your own common SourceSets and then depend on them:
Copy code
val jvmAndAndroidTest by creating {
  dependsOn(commonTest.get())
}

val jvmTest by getting {
  dependsOn(jvmAndAndroidTest)
}
        
val androidLibTest by getting {
  dependsOn(jvmAndAndroidTest)
}
in your more granular example you could deepen the tree even more, and to a degree automate it. However, if you don’t care so much about compiling but more about running, I can recommend creating your own
@Test…
annotations that only typealias to
@Test
on the platforms they work on,
@TestOnlyJvmAndroid
,
@TestExcludeNative
etc. This has a much cleaner folder structure, but of course it does not take care of compilation errors.
l

louiscad

06/04/2021, 10:12 AM
Maybe such a thing could work as a library blob thinking fast
j

jw

06/04/2021, 12:00 PM
Tried it a few years a ago as a library. Doesn't really work well.
Anyway for ignore you can exclude tests using test filters on the task itself which is easier to maintain in my opinion, but I was specifically after excluding from the source set as they do not compile.
l

louiscad

06/04/2021, 12:02 PM
Another alternative is to not make annotations, but a higher order function that skips the lambda when run on some platforms, depending on the parameters you give to it.
Probably kinda the same as using test filters
j

jw

06/04/2021, 12:08 PM
Yep, I suspect that to be about the same. And potentially more powerful if you want to filter on more granular runtime info
l

louiscad

06/04/2021, 12:18 PM
Power can be the same if you tweak the parameters of the higher order function I think. Could be a simple fun interface that is just a predicate, but that has companion object scoped pre-made builders/instances. E.g.: TestFilter.nativeOnly, TestFilter.concurrencyCapablePlatforms that you'd pass to the testing wrapper function.
r

russhwolf

06/04/2021, 12:28 PM
I started building a test annotations thing like that a couple years ago as a gradle plugin, with the idea being that you could detect what shared source-sets the project had and generate
@Test
and
@Ignore
annotations specific to each source-set. IIRC I backed off of it when special-casing Android stuff started to be a pain, but I don't think there were any actual blockers, I just wasn't sure if it'd be useful enough to be worth the effort.
l

louiscad

06/04/2021, 12:30 PM
What_kind_of_special_casing did you have to do for Android?
🐍 1
r

russhwolf

06/04/2021, 12:32 PM
When you ask most targets what source-sets they have, you just get "main" and "test" by default. But for Android there's more due to its richer system of build types and flavors.
I don't remember the details specifically but something in there was causing me trouble
l

louiscad

06/04/2021, 12:35 PM
Ah I see. With the higher order function approach, you'd not bump into these issues and tests would not need to deal with sourceSets