I finally enabled configuration cache in all of my...
# multiplatform
e
I finally enabled configuration cache in all of my libraries after a 3rd party blocker was resolved. One of my KMP repos started experiencing weird test failures after doing that, which I now know was caused by the configuration cache causing all test tasks across all targets to run in parallel. I was using
@BeforeTest
and
@AfterTest
functions in my test classes to cleanup database files, and what was happening was that tests from one target would delete the database files while tests from other targets were running. I ended up with what I think is a subpar solution (central function for creating and cleaning up the database with a test callback, and randomly generated database names) that I'd like to eventually improve. Is there a better way to handle this from
commonTest
?
t
I use a compiler plugin to get the name of the test function and then I create a unique directory for each test based on the platform and the name of the text function like this:
Copy code
@Test
fun processJson() {
    val path = clearedTestPath().resolve("test.json")
    // ...
}
I've found this approach very comfortable. Doc of `clearedTestPath`: > Get the path to a directory where a specific unit test can store its temporary files. > > Composes a unique, fully qualified path for a unit test. > > Creates the directory if it does not exist. > > Deletes the content of the directory if it exists. > > When used with the plugin active (which is almost everywhere, except core, gradle-plugin and kotlin-plugin), callSiteName is the fully qualified name of the function that calls clearedTestPath. > > Example: > > package some.test.pkg > > class SomeTest { > @Test > fun someTest() { > val testDir = clearedTestPath() > } > > Creates the directory: > > ./build/adaptive/test/JVM/some.test.pkg.SomeTest.someTest > > On iOS the tests are put into a directory like this: > > /Users/tiz/Library/Developer/CoreSimulator/Devices/D6554821-AD5A-46BC-9E25-A83F1BA38C9E/data/build/adaptive/test/iOS/
The benefit of this is that the files used / generated the tests are very easy to identify as the path contains the function name. This makes debugging easier.
e
Cool! Do you have that published?
t
Yes, but it is part of a rather big project, you might not want to pull in everything. Not that it would cause troubles, but it will slow your compilation down without real benefits if you just use it for this. The plugin is from this project: https://github.com/spxbhuhb/adaptive A Gradle config that uses it can be found here: https://github.com/spxbhuhb/adaptive-mpw-example (This does not use it for tests, but it it shows how to declare the dependency on the plugin). It would be fairly easy to cut out the part that does this.
By fairly easy I mean if you are somewhat familiar with Kotlin compiler plugins.
e
Thanks, that's awesome
e
in OP's case, just using a separate db per source set would suffice - configuration cache parallelizes Gradle tasks, but the test cases themselves are still sequential within each task (without further configuration). that's something that would be easy to
expect
-
actual
t
Are you sure about the tests are sequential? I had quite a few problems with that (I still have).
e
https://github.com/JakeWharton/cite is also a small compiler plugin that adds
__FILE__
__TYPE__
__MEMBER__
__LINE__
support
t
That might be better in this particular case than mine I think.
e
yes by default, and if they weren't then OP's tests would have failed before
t
I did have failing test because they run parallel and I had to set some JUnit settings to 1 to prevent that.
But it might be my bad somewhere.
e
https://docs.junit.org/current/user-guide/#writing-tests-parallel-execution junit.jupiter.execution.parallel.enabled defaults to false
anyhow I think there is other value to having a unique data path per test, I don't mean to say otherwise
there would be nice ways to do it in JUnit but cross-platform kotlin.test is pretty bare-bones
t
Is tests being sequential still true if I use coroutines? I'm just wondering.
No, I actually had out-of-memory without limiting test parallelism... something is fishy here.
Ah, maybe I'm in the wrong here, I do have parallel enabled in the case where I had OOM.
e
using
runTest
? that works the same as blocking tests on all platforms (except JS where they turn into promises that Mocha awaits)
t
I do use
runTest
but not everywhere, depending the situation. I also start coroutines in other dispatchers to perform tasks.
e
My other option was to expect / actual the db name for the tests which sounded bad up front, but isn't sounding so bad right now 😅