I share data between ScalaTest suites using a common singleton Object. This works fine when running on JVM, but to my surprise it fails on Scala.js. It seems on Scala.js a fresh instance of the program is used for each suite and the singletons are not shared.
Consider following code:
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
object SharedTestData {
var useCount = 0
def useMe(): Int = {
useCount += 1
useCount
}
}
class ATest extends AnyFlatSpec with Matchers {
"This" should "pass" in {
val used = SharedTestData.useMe()
info(s"Used $used times")
}
}
class BTest extends AnyFlatSpec with Matchers {
"This" should "pass as well" in {
val used = SharedTestData.useMe()
info(s"Used $used times")
}
}
The output from sbt test with project configured as Scala.js is:
[info] BTest:
[info] This
[info] - should pass as well
[info] + Used 1 times
[info] ATest:
[info] This
[info] - should pass
[info] + Used 1 times
[info] Run completed in 422 milliseconds.
[info] Total number of tests run: 2
Is there any technique which would allow me to share data between test suites on Scala.js? Some of the data take several minutes to compute and it is annoying computing them repeatedly.
By default, for speed, build tools such as sbt parallelize the execution of tests. In the Scala.js world, this is implemented by spawning several JavaScript VMs; one for each thread. Since separate JS VMs do not share memory, every top-level
objectin the code is instantiated once for each JS VM.The initialization of those objects should execute in parallel, so in most cases you shouldn't notice an increase in initialization time due to these separate instances. However, multi-tasking is complicated, and so it is possible in some cases for things to get slower.
You can enforce a single initialization by disabling parallel test execution in your build tool. In sbt, you can do it with the following setting:
That will ensure that only once JS VM is used. But it will also mean that all the tests in your test suite will run sequentially, without taking advantage of your multiple cores.