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

org.scalatest.fixture.MultipleFixtureWordSpec.scala Maven / Gradle / Ivy

/*
 * 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.fixture

import org.scalatest._

/**
 * A sister trait to org.scalatest.WordSpec that can pass multiple types of fixture objects into its tests.
 *
 * 

* This trait behaves similarly to trait org.scalatest.WordSpec, except that tests may take a fixture object, and unlike * a FixtureWordSpec, different tests may take different types of fixtures. This trait extends FixtureWordSpec * and mixes in ConfigMapFixture, which defines the Fixture type to be the configMap's * type (Map[String, Any]) and defines the withFixture method to simply pass the configMap * to the test function. To write tests that take fixtures of types other than Fixture (i.e., * Map[String, Any]), you can define implicit conversions from a function of type (<the fixture type>) => Unit * to a function of type (FixtureParam) => Unit. Each implicit conversion method serves as the with-fixture method for that type. *

* *

* Subclasses of this trait must, therefore, do two things differently from a plain old org.scalatest.WordSpec: *

* *
    *
  1. define implicit with<type>Fixture methods
  2. *
  3. write tests that take the different fixture types for which you've defined implicit conversion methods (You can also define tests that don't take a Fixture.)
  4. *
* *

* Here's an example that has two fixture types, String and List[Int]: *

* *
 * import org.scalatest.fixture.MultipleFixtureWordSpec
 * 
 * class MyWordSpec extends MultipleFixtureWordSpec {
 * 
 *   // A test that takes a String fixture
 *   implicit def withStringFixture(testFunction: String => Unit): FixtureParam => Unit =
 *     testFunction("howdy")
 * 
 *   // The "with-fixture" method for tests that take a List[Int] fixture
 *   implicit def withListFixture(testFunction: List[Int] => Unit): FixtureParam => Unit =
 *     configMap => testFunction(List(configMap.size))
 * 
 *   "Tests in a MultipleFixtureWordSpec" should {
 *
 *     // A test that takes a String fixture
 *     "take a string fixture" in { (s: String) =>
 *       assert(s === "howdy")
 *     }
 * 
 *     // A test that takes a List[Int] fixture
 *     "take a list fixture" in { (list: List[Int]) =>
 *       assert(list.size === 1)
 *     }
 * 
 *     // A test that takes no fixture
 *     "take no fixture" in { () =>
 *       assert(1 === 1)
 *     }
 *   }
 * }
 * 
* *

* The first method in this class, withStringFixture, is the implicit conversion function for tests that take a fixture * of type String. In this contrived example, the hard-coded string "howdy" is passed into the test: *

* *
 * implicit def withStringFixture(testFunction: String => Unit): FixtureParam => Unit =
 *   testFunction("howdy")
 * 
* *

* Although the result type of this implicit conversion method is FixtureParam => Unit, if a fixture doesn't need anything * from the configMap, you can leave off the configMap => at the beginning of the result function. The * reason this works is that MultipleFixtureWordSpec inherits an implicit conversion from a by-name parameter to * FixtureParam => Unit from supertrait FixtureWordSpec. This implicit conversion is used to enable * tests that take no fixture (such as the one named takes no fixture in this example) to be included in the * same class as tests that take type Fixture. That same implicit conversion is used here to allow you to leave off * the configMap => except when you actually need something from the configMap. By leaving it off, you * indicte to readers of the code that this fixture doesn't require anything from the configMap. *

* *

* The next method in this class, withListFixture, is the implicit conversion function for tests that take a * fixture of type List[Int]. In this contrived example, a List[Int] that contains one element, the * size of the configMap, is passed to the test function. Because the fixture uses the configMap, * it has an explicit configMap => parameter at the beginning of the result. (Remember, the Fixture * type is defined to be Map[String, Any], the type of the configMap, in supertrait ConfigMapFixture. *

* *

* Following the implicit conversion methods are the test declarations. One test is written to take the String fixture: *

* *
 * "take a string fixture" in { (s: String) =>
 *   assert(s === "howdy")
 * }
 * 
* *

* What happens at compile time is that because the Fixture type is Map[String, Any], the test method * should be passed a function from type (Map[String, Any]) => Unit, or using the type alias, (FixtureParam) => Unit. Passing * a function of type String => Unit as is attempted here is a type error. Thus the compiler will look around for an implicit * conversion that will fix the type error, and will find the withStringFixture method. Because this is the only implicit * conversion that fixes the type error, it will apply it, effectively generating this code: *

* *
 * // after the implicit withStringFixture method is applied by the compiler
 * "take a string fixture" in {
 *   withStringFixture { (s: String) =>
 *     assert(s === "howdy")
 *   }
 * }
 * 
* *

* After passing the (String) => Unit function to withStringFixture, the result will be of * type (FixtureParam) => Unit, which the test method expects. *

* *

* The next test is written to take the List[Int] fixture: *

* *
 * "take a list fixture" in { (list: List[Int]) =>
 *   assert(list.size === 1)
 * }
 * 
* *

* The compiler will apply the withListFixture implicit conversion in this case, effectively generating the following * code: *

* *
 * "take a list fixture" in {
 *   withListFixture { (list: List[Int]) =>
 *     assert(list.size === 1)
 *   }
 * }
 * 
* *

* Note that in a FixtureWordSpec, you need to specify the type of the fixture explicitly so the compiler knows * the type to convert from. So you must, for example, write: *

* *
 * "take a list fixture" in { (list: List[Int]) =>
 *   assert(list.size === 1)
 * }
 * 
* *

* The following attempt will fail to compile: *

* *
 * // won't compile, because list is inferred to be of type FixtureParam
 * "take a list fixture" in { list =>
 *   assert(list.size === 1)
 * }
 * 
* * @author Bill Venners */ trait MultipleFixtureWordSpec extends FixtureWordSpec with ConfigMapFixture




© 2015 - 2025 Weber Informatics LLC | Privacy Policy