Print execution data

Knowing that an example succeeded is fine but sometimes you want to display more information, like the time spent executing the example for instance, or some other state before and after each example.

This can be done by using the AroundEach trait and updating the Result of the example execution with whatever you want to display:

trait Timed extends AroundEach {
  def around[T : AsResult](t: =>T): Result = {
    // use `ResultExecution.execute` to catch possible exceptions
    val (result, timer) = withTimer(ResultExecution.execute(AsResult(t)))

    // update the result with a piece of text which will be displayed in the console
    result.updateExpected("Execution time: "+timer.time)
  }

  /** mesure the execution time of a piece of code */
  def withTimer[T](t: =>T): (T, SimpleTimer) = {
    val timer = (new SimpleTimer).start
    val result = t
    (result, timer.stop)
  }
}

When you execute a specification mixing the Timed trait you should see the timing of each example displayed in the console:

[info] TimedExecutionSpecification
[info]
[info] + example 1
[info] Execution time: 94 ms
[info] + example 2
[info] Execution time: 11 ms

Note that this is just an example. The same functionality is actually accessible with the [showtimes argument](Console output).

With the example description

More generally, you can both use the example description and the example body to display custom messages. To do this you need to intercept the creation of examples by creating a new FragmentFactory:

// a trait to create an Around context using the example description
trait TimedContext {
  def context(exampleDescription: String) = new Timed(exampleDescription)

  case class Timed(exampleDescription: String) extends Around {
    def around[T : AsResult](t: =>T): Result = {
      val (result, timer) = withTimer(ResultExecution.execute(AsResult(t)))
      result.updateExpected(s"Execution time for example $$exampleDescription: $${timer.time}")
    }

    def withTimer[T](t: =>T): (T, SimpleTimer) = {
      val timer = (new SimpleTimer).start
      val result = t
      (result, timer.stop)
    }
  }
}

class TimedSpecification extends Specification with TimedContext { def is = s2"""
 Example 1 $ok
 Example 2 $ok
"""

  // create a new DefaultFragmentFactory where the body of the example uses
  // the current example description
  override lazy val fragmentFactory = new DefaultFragmentFactory {
    override def example[T : AsResult](description: String, t: =>T): Fragment =
      super.example(description, context(description)(AsResult(t)))
  }
}