It is very tempting to use foreach
to create examples or results from a sequence of values:
(1 to 3).foreach(i => "example "+i ! { i must_== i })
The problem with foreach
is that the return value of the expression above is Unit
. So you won’t be able to use it in an acceptance specification or a mutable one.
When we want to create a list of examples we need to return a Fragments
object. The long-winded way to do so is to use a foldLeft
:
(1 to 3).foldLeft(Fragments.empty)((res, i) => res.append("example "+i ! { i must_== i }))
Or, a bit fancier with Scalaz:
// Fragments has a Monoid so you can use the foldMap method
(1 to 3).toList.foldMap(i => Fragments("example "+i ! { i must_== i }))
Because this is a recurring pattern there are two methods encapsulating it:
// when the function only returns a Fragment
Fragment.foreach(1 to 3)(i => "example "+i ! { i must_== i }): Fragments
// when the function returns a Fragments object
Fragments.foreach(1 to 3) { i =>
"examples for "+i ^ br^
"1 + "+i ! { (1 + i) must_== (i + 1) } ^ br^
"2 + "+i ! { (2 + i) must_== (i + 2) }
}: Fragments
Now you can create a list of examples inside a “should” block in a mutable specification:
class MySpec extends mutable.Specification {
"this block should have lots of examples" >> {
Fragment.foreach(1 to 1000) { i =>
"example "+i ! { i must_== i }
}
}
}
The same situation happens when you want to create a list of expectations inside an example:
class MySpec extends mutable.Specification {
"this example has a lot of expectations" >> {
Result.foreach(1 to 1000) { i =>
i must_== i
}
}
}
In that case the Result.foreach
method is the one to use, it returns a Result
that is the logical and
of all results. It will stop after the first issue (error or failure), if you want to collect all the results you can use Result.forall
.
Result.foreach
method uses the AsResult typeclass