Pramit
Pramit

Reputation: 1411

Little confused on the usefulness of beforeAll construct in ScalaTest

I have more of a philosophical confusion in-regards to the usefulness of methods like 'beforeAll' in scalaTest. I have been looking for an answer why the need to even have constructs like beforeAll? I do understand that there is a reason why this design decision was taken but not able to think it through. Can anyone help?

e.g. Suggested way as per tutorials online,

class TestExample extends FunSuite with BeforeAndAfterAll {
   private var _tempDir: File = _
   protected def tempDir: File = _tempDir

 override def beforeAll(): Unit = {
  super.beforeAll()
  _tempDir = Utils.createTempDir(namePrefix = this.getClass.getName)
  }

  test("...") {
   // using the variable in the function
  }
 } 

vs

class TestExample extends FunSuite with BeforeAndAfterAll {
   private val tempDir: File = Utils.createTempDir(namePrefix = 
   this.getClass.getName) 
  }

  test("...") {
   // Use the initialized variable here.
 } 

Upvotes: 2

Views: 2512

Answers (2)

Ian Robertson
Ian Robertson

Reputation: 1348

One point worth noting is that some runners (such as the ScalaTest ant task, and Intellij IDEA), will instantiate all tests instances before running any tests. If your setup code happens to interact with any global variables or external state, then you probably want to defer those interactions until the test is run.

As a simple (contrived) example, suppose your code under test includes

Object Singleton {
  var foo = ""
}

and you have two test classes:

class Test1 extends FunSuite {
  Singleton.foo = "test1"

  test("...") {
    Singleton.foo should be("test1")
  }
}

class Test1 extends FunSuite {
  Singleton.foo = "test2"

  test("...") {
    Singleton.foo should be("test2")
  }
}

If both classes are instantiated before any tests are run, then at least one of your two tests will fail. Conversely, if you defer your initialize work until beforeAll, you'll not see the same interference between tests.

Upvotes: 1

Bill Venners
Bill Venners

Reputation: 3669

If you have cleanup to do in afterAll, I think it is symmetric to do setup in beforeAll. Also if you need to do some side effect that doesn't involve initializing instance variables, that can go in beforeAll. In the example you gave, though, where you don't have any cleanup to do in afterAll and all you're doing before all tests is initializing instance variables, I'd do with plain old initialization.

One other difference between val initializers and beforeAll is val initializers happen when the class is instantiated, whereas beforeAll happens later, when the instance is executed. If you want to delay the initialization until the class is run, you can use lazy vals.

Upvotes: 3

Related Questions