BeforeAndAfterAllConfigMap
Trait that can be mixed into suites that need methods that make use of the config map invoked before and/or after executing the suite.
This trait allows code to be executed before and/or after all the tests and nested suites of a suite are run. This trait overrides run and calls the beforeAll(ConfigMap) method, then calls super.run. After the super.run invocation completes, whether it returns normally or completes abruptly with an exception, this trait's run method will invoke afterAll(ConfigMap).
Note that this trait differs from BeforeAndAfterAll in that it gives the beforeAll and afterAll code access to the config map. If you don't need the config map, use BeforeAndAfterAll instead.
Trait BeforeAndAfterAllConfigMap defines beforeAll and afterAll methods that take a configMap. This trait's implemention of each method does nothing.
For example, the following ExampleSpec mixes in BeforeAndAfterAllConfigMap and in beforeAll, creates and writes to a temp file, taking the name of the temp file from the configMap. This same configMap is then passed to the run methods of the nested suites, OneSpec, TwoSpec, RedSpec, and BlueSpec, so those suites can access the filename and, therefore, the file's contents. After all of the nested suites have executed, afterAll is invoked, which again grabs the file name from the configMap and deletes the file. Each of these five test classes extend trait TempFileExistsSpec, which defines a test that ensures the temp file exists. (Note: if you're unfamiliar with the withFixture(OneArgTest) approach to shared fixtures, check out the documentation for trait fixture.FlatSpec.)
package org.scalatest.examples.beforeandafterallconfigmap
import org.scalatest._
import java.io._
trait TempFileExistsSpec extends fixture.FlatSpec {
type FixtureParam = File
override def withFixture(test: OneArgTest) = {
val fileName = test.configMap.getRequired[String]("tempFileName")
val file = new File(fileName)
withFixture(test.toNoArgTest(file)) // loan the fixture to the test
}
"The temp file" should ("exist in " + suiteName) in { file =>
assert(file.exists)
}
}
class OneSpec extends TempFileExistsSpec
class TwoSpec extends TempFileExistsSpec
class RedSpec extends TempFileExistsSpec
class BlueSpec extends TempFileExistsSpec
class ExampleSpec extends Suites(
new OneSpec,
new TwoSpec,
new RedSpec,
new BlueSpec
) with TempFileExistsSpec with BeforeAndAfterAllConfigMap {
private val tempFileName = "tempFileName"
// Set up the temp file needed by the test, taking
// a file name from the config map
override def beforeAll(cm: ConfigMap) {
assume(
cm.isDefinedAt(tempFileName),
"must place a temp file name in the config map under the key: " + tempFileName
)
val fileName = cm.getRequired[String](tempFileName)
val writer = new FileWriter(fileName)
try writer.write("Hello, suite of tests!")
finally writer.close()
}
// Delete the temp file
override def afterAll(cm: ConfigMap) {
val fileName = cm.getRequired[String]("tempFileName")
val file = new File(fileName)
file.delete()
}
}
Running the above class in the interpreter will give an error if you don't supply a mapping for "tempFileName" in the config map:
scala> org.scalatest.run(new ExampleSpec) ExampleSpec: Exception encountered when invoking run on a suite. *** ABORTED *** Exception encountered when invoking run on a suite. (:30) *** RUN ABORTED *** An exception or error caused a run to abort: must place a temp file name in the config map under the key: tempFileName ( :30)
If you do supply a mapping for "tempFileName" in the config map, you'll see that the temp file is available to all the tests:
scala> (new ExampleSpec).execute(configMap = ConfigMap("tempFileName" -> "tmp.txt"))
ExampleSpec:
OneSpec:
The temp file
- should exist in OneSpec
TwoSpec:
The temp file
- should exist in TwoSpec
RedSpec:
The temp file
- should exist in RedSpec
BlueSpec:
The temp file
- should exist in BlueSpec
The temp file
- should exist in ExampleSpec
Note: As of 2.0.M5, this trait uses the newly added Status result of Suite's "run" methods to ensure that the code in afterAll is executed after all the tests and nested suites are executed even if a Distributor is passed.
Note that it is not guaranteed that afterAll is invoked from the same thread as beforeAll, so if there's any shared state between beforeAll and afterAll you'll need to make sure they are synchronized correctly.
Attributes
- Graph
-
- Supertypes
- Self type