Giovanni Azua Giovanni Azua - 2 months ago 17
Scala Question

ScalaTest: Is there a flaw defining Test Suites as object rather than class?

I have a very specific use-case and in order to reduce instantiation time for the test suites I define them as an object and not as a class e.g.

import org.scalatest._
import scala.collection.mutable.Stack

object StackSuite extends FunSuite with Matchers {
test("stackShouldPopValuesIinLastInFirstOutOrder") {
val stack = new Stack[Int]
stack.push(1)
stack.push(2)
stack.pop() should equal(2)
stack.pop() should equal(1)
}
}


This works but is there a fundamental issue or flaw regarding doing this? separate from the multithreading issue should each test be executed separately and in the unfortunate case of having modifyable state at the suite level.

UPDATE: when I say "reduce instantiation time" I meant overall e.g. accounting for heavyweight fixture data inside the object/class and not simply the pure Suite class instantiation time. Since object is a singleton then it would be a lookup rather than an instantiation of a new class.

I need to do this in order to distribute millions of tests across a grid of computers. Some tests are standard scalatest others are evaluating the permutations of a set of input parameters therefore the need to reduce the startup time for the instantiation of the Suite.

btw I do this to execute each test in a cluster machine:

import scala.reflect.runtime.universe

// I receive the suite and test names as input
val suite = "com.mycomp.StackSuite"
val test = "stackShouldPopValuesIinLastInFirstOutOrder"

val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
val module = runtimeMirror.staticModule(suite)
val obj = runtimeMirror.reflectModule(module)
val status = obj.asInstanceOf[TestSuite].execute(test)

Answer

in order to reduce instantiation time for the test suites I define them as an object and not as a class

I had a quick look at org.scalatest.tools.Runner (and DiscoverySuite) implementation, and I don't think this can reduce the instantiation time.

Remember how objects are actually compiled on JVM: you have a class StackSuite$ which extends Suite and has a public parameterless constructor (because it has to be called from StackSuite's static initializer). It's found and handled precisely like a class StackSuite would be.

EDIT: if you find the suite and run it yourself in this way instead of using ScalaTest's own API, then yes, you'll get a lookup instead of instantiation. Assuming no concurrency issues, there should be no problem: execute itself is threadsafe.

Comments