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

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

/*
 * Copyright 2001-2013 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

import org.scalatest._
import OutcomeOf.outcomeOf
import org.scalactic._

/**
 * The base trait for ScalaTest's synchronous testing styles that accept a fixture
 * object passed into tests. This trait defines a
 * withFixture lifecycle method that takes as its parameter a test function
 * that accepts a fixture object and returns an Outcome.
 *
 * 

* The abstract withFixture method add by this trait has the * following signature: *

* *
 * def withFixture(test: OneArgTest): Outcome
 * 
* * The apply method of test function interface, * OneArgTest, also returns Outcome: *

* *
 * // In trait OneArgTest:
 * def apply(fixture: FixtureParam): Outcome
 * 
* *

* Because the result of a test is an Outcome, when the test function returns, the test body must have determined an outcome already. It * will already be one of Succeeded, Failed, Canceled, or Pending. This is * also true when withFixture(OneArgTest) returns: because the result type of withFixture(OneArgTest) is Outcome, * the test has by definition already finished execution. *

* *

* The recommended way to ensure cleanup is performed after a test body finishes execution is * to use a try-finally clause. * Using try-finally will ensure that cleanup will occur whether * the test function completes abruptly by throwing a suite-aborting exception, or returns * normally yielding an Outcome. Note that the only situation in which a test function * will complete abruptly with an exception is if the test body throws a suite-aborting exception. * Any other exception will be caught and reported as either a Failed, Canceled, * or Pending. *

* *

* To enable the stacking of traits that define withFixture(NoArgTest), it is a good idea to let * withFixture(NoArgTest) invoke the test function instead of invoking the test * function directly. To do so, you'll need to convert the OneArgTest to a NoArgTest. You can do that by passing * the fixture object to the toNoArgTest method of OneArgTest. In other words, instead of * writing “test(theFixture)”, you'd delegate responsibility for * invoking the test function to the withFixture(NoArgTest) method of the same instance by writing: *

* *
 * withFixture(test.toNoArgTest(theFixture))
 * 
* *

* The withFixture method is designed to be stacked, and to enable this, you should always call the super implementation * of withFixture, and let it invoke the test function rather than invoking the test function directly. In other words, instead of writing * “test(...)”, you should write “super.withFixture(test)”. Thus, the recommended * structure of a withFixture implementation that performs cleanup looks like this: *

* *
 * // Your implementation
 * type FixtureParam = String
 *
 * override def withFixture(test: OneArgTest) = {
 *   // Perform setup here
 *   val theFixture = "hello"
 *   try {
 *     withFixture(test.toNoArgTest(theFixture)) // Invoke the test function
 *   } finally {
 *     // Perform cleanup here
 *   }
 * }
 * 
* *

* If you have no cleanup to perform, you can write withFixture like this instead: *

* *
 * // Your implementation
 * type FixtureParam = String
 *
 * override def withFixture(test: NoArgTest) = {
 *   // Perform setup here
 *   val theFixture = "hello"
 *   withFixture(test.toNoArgTest(theFixture)) // Invoke the test function
 * }
 * 
* *

* If you want to perform an action only for certain outcomes, you can use * a pattern match. * For example, if you want to perform an action if a test fails, you'd * match on Failed, like this: *

* *
 * // Your implementation
 * type FixtureParam = String
 *
 * override def withFixture(test: NoArgTest) = {
 *
 *   // Perform setup here
 *   val theFixture = "hello"
 *
 *   val outcome = withFixture(test.toNoArgTest(theFixture)) // Invoke the test function
 *
 *   outcome match {
 *     case failed: Failed =>
 *       // perform action that you want to occur
 *       // only if a test fails here
 *       failed
 *     case other => other
 *   }
 * }
 * 
* *

* If you want to change the outcome in some way in withFixture, you can also * use a pattern match. * For example, if a particular exception intermittently causes a test to fail, and can * transform those failures into cancelations, like this: *

* *
 * // Your implementation
 * type FixtureParam = String
 *
 * override def withFixture(test: NoArgTest) = {
 *
 *   val theFixture = "hello"
 *
 *   withFixture(test.toNoArgTest(theFixture)) match {
 *     case Failed(ex: ParticularException) =>
 *       Canceled("Muting flicker", ex)
 *     case other => other
 *   }
 * }
 * 
*/ trait FixtureTestSuite extends org.scalatest.FixtureSuite with org.scalatest.TestSuite { thisTestSuite => /** * A test function taking a fixture parameter and returning an Outcome. * *

* For more detail and examples, see the * documentation for trait fixture.FlatSpec. *

*/ protected trait OneArgTest extends (FixtureParam => Outcome) with TestData { thisOneArgTest => /** * Runs the test, using the passed FixtureParam. * * @param fixture the FixtureParam * @return an instance of Outcome */ def apply(fixture: FixtureParam): Outcome /** * Convert this OneArgTest to a NoArgTest whose * name and configMap methods return the same values * as this OneArgTest, and whose apply method invokes * this OneArgTest's apply method, * passing in the given fixture. * *

* This method makes it easier to invoke the withFixture method * that takes a NoArgTest. For example, if a FixtureSuite * mixes in SeveredStackTraces, it will inherit an implementation * of withFixture(NoArgTest) provided by * SeveredStackTraces that implements the stack trace severing * behavior. If the FixtureSuite does not delegate to that * withFixture(NoArgTest) method, the stack trace severing behavior * will not happen. Here's how that might look in a FixtureSuite * whose FixtureParam is StringBuilder: *

* *
     * def withFixture(test: OneArgTest) = {
     *   withFixture(test.toNoArgTest(new StringBuilder))
     * }
     * 
* *

* Invoking this method has no side effect. It just returns a NoArgTest whose * apply method invokes apply on this OneArgTest, passing * in the FixtureParam passed to toNoArgTest. *

* * @param fixture the FixtureParam * @return an new instance of NoArgTest */ def toNoArgTest(fixture: FixtureParam) = new NoArgTest { val name = thisOneArgTest.name val configMap = thisOneArgTest.configMap def apply(): Outcome = { thisOneArgTest(fixture) } val scopes = thisOneArgTest.scopes val text = thisOneArgTest.text val tags = thisOneArgTest.tags val pos = thisOneArgTest.pos } } /** * Companion object for OneArgTest that provides factory method to create new OneArgTest * instance by passing in a OneArgTest and a FixtureParam => Outcome function. */ object OneArgTest { /** * Create new OneArgTest instance. * * @param test a OneArgTest * @param f a FixtureParam => Outcome function * @return a new instance of OneArgTest, which will call the passed f function in its apply method */ def apply(test: OneArgTest)(f: FixtureParam => Outcome): OneArgTest = { new OneArgTest { def apply(fixture: FixtureParam): Outcome = { f(fixture) } val text: String = test.text val configMap: ConfigMap = test.configMap val scopes: collection.immutable.IndexedSeq[String] = test.scopes val name: String = test.name val tags: Set[String] = test.tags val pos: Option[source.Position] = test.pos } } } /** * Run the passed test function with a fixture created by this method. * *

* This method should create the fixture object needed by the tests of the * current suite, invoke the test function (passing in the fixture object), * and if needed, perform any clean up needed after the test completes. * For more detail and examples, see the main documentation for this trait. *

* * @param test the OneArgTest to invoke, passing in a fixture * @return an instance of Outcome */ protected def withFixture(test: OneArgTest): Outcome private[scalatest] class TestFunAndConfigMap(val name: String, test: FixtureParam => Any, val configMap: ConfigMap) extends OneArgTest { def apply(fixture: FixtureParam): Outcome = { outcomeOf { test(fixture) } } private val testData = testDataFor(name, configMap) val scopes = testData.scopes val text = testData.text val tags = testData.tags val pos = testData.pos } private[scalatest] class FixturelessTestFunAndConfigMap(override val name: String, test: () => Any, override val configMap: ConfigMap) extends NoArgTest { def apply(): Outcome = { outcomeOf { test() } } private val testData = testDataFor(name, configMap) val scopes = testData.scopes val text = testData.text val tags = testData.tags val pos = testData.pos } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy