org.scalatest.fixture

trait MultipleFixtureFeatureSpec

[source: org/scalatest/fixture/MultipleFixtureFeatureSpec.scala]

trait MultipleFixtureFeatureSpec
extends FixtureFeatureSpec with ConfigMapFixture
A sister trait to org.scalatest.FeatureSpec that can pass multiple types of fixture objects into its tests.

This trait behaves similarly to trait org.scalatest.FeatureSpec, except that tests may take a fixture object, and unlike a FixtureFeatureSpec, different tests may take different types of fixtures. This trait extends FixtureFeatureSpec 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.FeatureSpec:

  1. define implicit with<type>Fixture methods
  2. 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.)

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

 import org.scalatest.fixture.MultipleFixtureFeatureSpec
 
 class MyFeatureSpec extends MultipleFixtureFeatureSpec {
 
   // The "with-fixture" method for tests that take 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))
 
   // A test that takes a String fixture
   scenario("takes a string fixture") { (s: String) =>
     assert(s === "howdy")
   }
 
   // A test that takes a List[Int] fixture
   scenario("takes a list fixture") { (list: List[Int]) =>
     assert(list.size === 1)
   }
 
   // A test that takes no fixture
   scenario("takes no fixture") { () =>
     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 MultipleFixtureFeatureSpec inherits an implicit conversion from a by-name parameter to FixtureParam => Unit from supertrait FixtureFeatureSpec. 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:

 scenario("takes a string fixture") { (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
 scenario("takes a string fixture") {
   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:

 scenario("takes a list fixture") { (list: List[Int]) =>
   assert(list.size === 1)
 }
 

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

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

Note that in a FixtureFeatureSpec, 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:

 scenario("takes a list fixture") { (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
 scenario("takes a list fixture") { list =>
   assert(list.size === 1)
 }
 
Author
Bill Venners
Methods inherited from ConfigMapFixture
withFixture
Methods inherited from FixtureFeatureSpec
info, scenario, scenario, ignore, ignore, feature, tags, runTest, runTests, testNames, run, scenariosFor, convertPendingToFixtureFunction, convertNoArgToFixtureFunction
Methods inherited from Suite
nestedSuites, execute, execute, execute, execute, groups, withFixture, runNestedSuites, suiteName, pending, pendingUntilFixed, expectedTestCount
Methods inherited from Assertions
assert, assert, assert, assert, convertToEqualizer, intercept, expect, expect, fail, fail, fail, fail
Methods inherited from AnyRef
getClass, hashCode, equals, clone, toString, notify, notifyAll, wait, wait, wait, finalize, ==, !=, eq, ne, synchronized
Methods inherited from Any
==, !=, isInstanceOf, asInstanceOf

Copyright (C) 2001-2009 Artima, Inc. All rights reserved.