All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalatest.BeforeAndAfterAll.scala Maven / Gradle / Ivy

There is a newer version: 2.0.M6-SNAP27
Show newest version
/*
 * Copyright 2001-2009 Artima, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.scalatest

/**
 * Trait that can be mixed into suites that need methods invoked before and 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 (the main run method that
 * takes seven parameters, an optional test name, reporter, stopper, filter, configMap, optional distributor,
 * and tracker) and calls the
 * beforeAll 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.
 *
 * 

* Trait BeforeAndAfterAll defines two overloaded variants each of beforeAll * and afterAll, one that takes a configMap and another that takes no * arguments. This traits implemention of the variant that takes the configMap * simply invokes the variant that takes no parameters, which does nothing. Thus you can override * whichever variant you want. If you need something from the configMap before * all tests and nested suites are run, override beforeAll(Map[String, Any]). Otherwise, * override beforeAll(). *

* *

* For example, the following MasterSuite mixes in BeforeAndAfterAll 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, OneSuite, TwoSuite, RedSuite, * and BlueSuite, 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: *

* *
 * import org.scalatest.SuperSuite
 * import org.scalatest.BeforeAndAfterAll
 * import java.io.FileReader
 * import java.io.FileWriter
 * import java.io.File
 *
 * class MasterSuite extends Suite with BeforeAndAfterAll {
 *
 *   private val FileNameKeyInGoodies = "tempFileName"
 *
 *   // Set up the temp file needed by the test, taking
 *   // a file name from the configMap
 *   override def beforeAll(configMap: Map[String, Any]) {
 *
 *     require(
 *       configMap.isDefinedAt(FileNameKeyInGoodies),
 *       "must place a temp file name in the configMap under the key: " + FileNameKeyInGoodies
 *     )
 *
 *     val fileName = configMap(tempFileName)
 *
 *     val writer = new FileWriter(fileName)
 *     try {
 *       writer.write("Hello, suite of tests!")
 *     }
 *     finally {
 *       writer.close()
 *     }
 *   }
 *
 *   override def nestedSuites =
 *     List(new OneSuite, new TwoSuite, new RedSuite, new BlueSuite)
 * 
 *   // Delete the temp file
 *   override def afterAll(configMap: Map[String, Any]) {
 *     // No need to require that configMap contains the key again because it won't get
 *     // here if it didn't contain the key in beforeAll 
 *     val fileName = configMap(tempFileName))
 *     val file = new File(fileName)
 *     file.delete()
 *   }
 * }
 * 
* *

* Because the BeforeAndAfterAll trait invokes super.run to run the suite, you may need to * mix this trait in last to get the desired behavior. For example, this won't * work, because BeforeAndAfterAll is "super" to FunSuite: *

*
 * class MySuite extends BeforeAndAfterAll with FunSuite
 * 
*

* You'd need to turn it around, so that FunSuite is "super" to BeforeAndAfterAll, like this: *

*
 * class MySuite extends FunSuite with BeforeAndAfterAll
 * 
* * Note: This trait does not currently ensure that the code in afterAll is executed after * all the tests and nested suites are executed if a Distributor is passed. The * plan is to do that eventually, but in the meantime, be aware that afterAll is * guaranteed to be run after all the tests and nested suites only when they are run * sequentially. * * @author Bill Venners */ trait BeforeAndAfterAll extends AbstractSuite { this: Suite => /** * Defines a method to be run before any of this suite's tests or nested suites are run. * *

* This trait's implementation * of run invokes the overloaded form of this method that * takes a configMap before executing * any tests or nested suites. This trait's implementation of that beforeAll(Map[String, Any]) * method simply invokes this beforeAll() * method. Thus this method can be used to set up a test fixture * needed by the entire suite, when you don't need anything from the configMap. * This trait's implementation of this method does nothing. *

*/ protected def beforeAll() = () /** * Defines a method (that takes a configMap) to be run before any * of this suite's tests or nested suites are run. * *

* This trait's implementation * of run invokes this method before executing * any tests or nested suites (passing in the configMap passed to it), thus this * method can be used to set up a test fixture * needed by the entire suite. This trait's implementation of this method invokes the * overloaded form of beforeAll that takes no configMap. *

*/ protected def beforeAll(configMap: Map[String, Any]) { beforeAll() } /** * Defines a method to be run after all of this suite's tests and nested suites have * been run. * *

* This trait's implementation * of run invokes the overloaded form of this method that * takes a configMap after executing * all tests and nested suites. This trait's implementation of that afterAll(Map[String, Any]) method simply invokes this * afterAll() method. Thus this method can be used to tear down a test fixture * needed by the entire suite, when you don't need anything from the configMap. * This trait's implementation of this method does nothing. *

*/ protected def afterAll() = () /** * Defines a method (that takes a configMap) to be run after * all of this suite's tests and nested suites have been run. * *

* This trait's implementation * of run invokes this method after executing all tests * and nested suites (passing in the configMap passed to it), thus this * method can be used to tear down a test fixture * needed by the entire suite. This trait's implementation of this method invokes the * overloaded form of afterAll that takes no configMap. *

*/ protected def afterAll(configMap: Map[String, Any]) { afterAll() } /** * Execute a suite surrounded by calls to beforeAll and afterAll. * *

* This trait's implementation of this method ("this method") invokes beforeAll(Map[String, Any]) * before executing any tests or nested suites and afterAll(Map[String, Any]) * after executing all tests and nested suites. It runs the suite by invoking super.run, passing along * the seven parameters passed to it. *

* *

* If any invocation of beforeAll completes abruptly with an exception, this * method will complete abruptly with the same exception. If any call to * super.run completes abruptly with an exception, this method * will complete abruptly with the same exception, however, before doing so, it will * invoke afterAll. If afterAll also completes abruptly with an exception, this * method will nevertheless complete abruptly with the exception previously thrown by super.run. * If super.run returns normally, but afterAll completes abruptly with an * exception, this method will complete abruptly with the same exception. *

*/ abstract override def run(testName: Option[String], reporter: Reporter, stopper: Stopper, filter: Filter, configMap: Map[String, Any], distributor: Option[Distributor], tracker: Tracker) { var thrownException: Option[Throwable] = None beforeAll(configMap) try { super.run(testName, reporter, stopper, filter, configMap, distributor, tracker) } catch { case e: Exception => thrownException = Some(e) } finally { try { afterAll(configMap) // Make sure that afterAll is called even if run completes abruptly. thrownException match { case Some(e) => throw e case None => } } catch { case laterException: Exception => thrownException match { // If both run and afterAll throw an exception, report the test exception case Some(earlierException) => throw earlierException case None => throw laterException } } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy