Package

org.scalatest

fixture

Permalink

package fixture

Visibility
  1. Public
  2. All

Type Members

  1. abstract class AsyncFeatureSpec extends AsyncFeatureSpecLike

    Permalink
  2. trait AsyncFeatureSpecLike extends AsyncSuite with AsyncTestRegistration

    Permalink

    Implementation trait for class fixture.FeatureSpec, which is a sister class to org.scalatest.FeatureSpec that can pass a fixture object into its tests.

    Implementation trait for class fixture.FeatureSpec, which is a sister class to org.scalatest.FeatureSpec that can pass a fixture object into its tests.

    fixture.FeatureSpec is a class, not a trait, to minimize compile time given there is a slight compiler overhead to mixing in traits compared to extending classes. If you need to mix the behavior of fixture.FeatureSpec into some other class, you can use this trait instead, because class fixture.FeatureSpec does nothing more than extend this trait and add a nice toString implementation.

    See the documentation of the class for a detailed overview of fixture.FeatureSpec.

    Annotations
    @Finders()
  3. abstract class FeatureSpec extends FeatureSpecLike

    Permalink

    A sister class to org.scalatest.FeatureSpec that can pass a fixture object into its tests.

    A sister class to org.scalatest.FeatureSpec that can pass a fixture object into its tests.

    Recommended Usage: Use class fixture.FeatureSpec in situations for which FeatureSpec would be a good choice, when all or most tests need the same fixture objects that must be cleaned up afterwards. Note: fixture.FeatureSpec is intended for use in special situations, with class FeatureSpec used for general needs. For more insight into where fixture.FeatureSpec fits in the big picture, see the withFixture(OneArgTest) subsection of the Shared fixtures section in the documentation for class FeatureSpec.

    Class fixture.FeatureSpec behaves similarly to class org.scalatest.FeatureSpec, except that tests may have a fixture parameter. The type of the fixture parameter is defined by the abstract FixtureParam type, which is a member of this class. This trait also has an abstract withFixture method. This withFixture method takes a OneArgTest, which is a nested trait defined as a member of this class. OneArgTest has an apply method that takes a FixtureParam. This apply method is responsible for running a test. This class's runTest method delegates the actual running of each test to withFixture(OneArgTest), passing in the test code to run via the OneArgTest argument. The withFixture(OneArgTest) method (abstract in this class) is responsible for creating the fixture argument and passing it to the test function.

    Subclasses of this class must, therefore, do three things differently from a plain old org.scalatest.FeatureSpec:

    • define the type of the fixture parameter by specifying type FixtureParam
    • define the withFixture(OneArgTest) method
    • write tests that take a fixture parameter
    • (You can also define tests that don't take a fixture parameter.)

    If the fixture you want to pass into your tests consists of multiple objects, you will need to combine them into one object to use this class. One good approach to passing multiple fixture objects is to encapsulate them in a case class. Here's an example:

    case class FixtureParam(file: File, writer: FileWriter)
    

    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))
    

    Here's a complete example:

    package org.scalatest.examples.featurespec.oneargtest
    
    import org.scalatest.fixture
    import java.io._
    
    class ExampleSpec extends fixture.FeatureSpec {
    
      case class FixtureParam(file: File, writer: FileWriter)
    
      def withFixture(test: OneArgTest) = {
    
        // create the fixture
        val file = File.createTempFile("hello", "world")
        val writer = new FileWriter(file)
        val theFixture = FixtureParam(file, writer)
    
        try {
          writer.write("ScalaTest is designed to be ") // set up the fixture
          withFixture(test.toNoArgTest(theFixture)) // "loan" the fixture to the test
        }
        finally writer.close() // clean up the fixture
      }
    
      feature("Simplicity") {
        scenario("User needs to read test code written by others") { f =>
          f.writer.write("encourage clear code!")
          f.writer.flush()
          assert(f.file.length === 49)
        }
    
        scenario("User needs to understand what the tests are doing") { f =>
          f.writer.write("be easy to reason about!")
          f.writer.flush()
          assert(f.file.length === 52)
        }
      }
    }
    

    If a test fails, the OneArgTest function will result in a Failed wrapping the exception describing the failure. To ensure clean up happens even if a test fails, you should invoke the test function from inside a try block and do the cleanup in a finally clause, as shown in the previous example.

    Sharing fixtures across classes

    If multiple test classes need the same fixture, you can define the FixtureParam and withFixture(OneArgTest) implementations in a trait, then mix that trait into the test classes that need it. For example, if your application requires a database and your integration tests use that database, you will likely have many test classes that need a database fixture. You can create a "database fixture" trait that creates a database with a unique name, passes the connector into the test, then removes the database once the test completes. This is shown in the following example:

    package org.scalatest.examples.fixture.featurespec.sharing
    
    import java.util.concurrent.ConcurrentHashMap
    import org.scalatest.fixture
    import DbServer._
    import java.util.UUID.randomUUID
    
    object DbServer { // Simulating a database server
      type Db = StringBuffer
      private val databases = new ConcurrentHashMap[String, Db]
      def createDb(name: String): Db = {
        val db = new StringBuffer
        databases.put(name, db)
        db
      }
      def removeDb(name: String) {
        databases.remove(name)
      }
    }
    
    trait DbFixture { this: fixture.Suite =>
    
      type FixtureParam = Db
    
      // Allow clients to populate the database after
      // it is created
      def populateDb(db: Db) {}
    
      def withFixture(test: OneArgTest) {
        val dbName = randomUUID.toString
        val db = createDb(dbName) // create the fixture
        try {
          populateDb(db) // setup the fixture
          withFixture(test.toNoArgTest(db)) // "loan" the fixture to the test
        }
        finally removeDb(dbName) // clean up the fixture
      }
    }
    
    class ExampleSpec extends fixture.FeatureSpec with DbFixture {
    
      override def populateDb(db: Db) { // setup the fixture
        db.append("ScalaTest is designed to ")
      }
    
      feature("Simplicity") {
    
        scenario("User needs to read test code written by others") { db =>
          db.append("encourage clear code!")
          assert(db.toString === "ScalaTest is designed to encourage clear code!")
        }
    
        scenario("User needs to understand what the tests are doing") { db =>
          db.append("be easy to reason about!")
          assert(db.toString === "ScalaTest is designed to be easy to reason about!")
        }
    
        scenario("User needs to write tests") { () =>
          val buf = new StringBuffer
          buf.append("ScalaTest is designed to be ")
          buf.append("easy to learn!")
          assert(buf.toString === "ScalaTest is designed to be easy to learn!")
        }
      }
    }
    

    Often when you create fixtures in a trait like DbFixture, you'll still need to enable individual test classes to "setup" a newly created fixture before it gets passed into the tests. A good way to accomplish this is to pass the newly created fixture into a setup method, like populateDb in the previous example, before passing it to the test function. Classes that need to perform such setup can override the method, as does ExampleSpec.

    If a test doesn't need the fixture, you can indicate that by providing a no-arg instead of a one-arg function, as is done in the third test in the previous example, “Test code should be clear”. In other words, instead of starting your function literal with something like “db =>”, you'd start it with “() =>”. For such tests, runTest will not invoke withFixture(OneArgTest). It will instead directly invoke withFixture(NoArgTest).

    Both examples shown above demonstrate the technique of giving each test its own "fixture sandbox" to play in. When your fixtures involve external side-effects, like creating files or databases, it is a good idea to give each file or database a unique name as is done in these examples. This keeps tests completely isolated, allowing you to run them in parallel if desired. You could mix ParallelTestExecution into either of these ExampleSpec classes, and the tests would run in parallel just fine.

    Annotations
    @Finders()
  4. trait FeatureSpecLike extends Suite with TestRegistration with Informing with Notifying with Alerting with Documenting

    Permalink

    Implementation trait for class fixture.FeatureSpec, which is a sister class to org.scalatest.FeatureSpec that can pass a fixture object into its tests.

    Implementation trait for class fixture.FeatureSpec, which is a sister class to org.scalatest.FeatureSpec that can pass a fixture object into its tests.

    fixture.FeatureSpec is a class, not a trait, to minimize compile time given there is a slight compiler overhead to mixing in traits compared to extending classes. If you need to mix the behavior of fixture.FeatureSpec into some other class, you can use this trait instead, because class fixture.FeatureSpec does nothing more than extend this trait and add a nice toString implementation.

    See the documentation of the class for a detailed overview of fixture.FeatureSpec.

    Annotations
    @Finders()

Ungrouped