Search code examples
scalaunit-testingcollectionsspecs2

Can Specs2 Result.foreach be made to work like a matcher?


Using Specs2, if I do:

    1 must beEqualTo(2)
    1 must beEqualTo(1)

The test fails (as expected)

If I do:

    Result.foreach(1 to 10) { i =>
      i must_== 2
    }
    Result.foreach(1 to 10) { i =>
      i must_== i
    }

The test passes

For Result.foreach I have to use and to make the test fail (as expected):

    Result.foreach(1 to 10) { i =>
      i must_== 2
    } and
    Result.foreach(1 to 10) { i =>
      i must_== i
    }

Why is this? Is there a way to make it work in a less surprising way? This is very error prone - it's way too easy to not notice somebody didn't type and

I checked the Specs2 user guide but there's no mention of this behaviour that I can find.


Solution

  • This should probably be better documented. The Result.foreach function is indeed supposed to be non side-effecting. If you want side-effects you can call foreach directly in your specification because this one is wired in with the "throwing" behaviour of a mutable specification:

    class TestMutableSpec extends mutable.Specification {
    
      "foreach must fail" >> {
        foreach(1 to 10) { i =>
          i must_== 2
        }
        foreach(1 to 10) { i =>
          i must_== i
        }
      }
    }
    

    returns

    [info] TestMutableSpec
    [error] x foreach must fail
    [error]  There are 9 failures
    [error]  1 != 2
    [error]  3 != 2
    [error]  4 != 2
    [error]  5 != 2
    [error]  6 != 2
    [error]  7 != 2
    [error]  8 != 2
    [error]  9 != 2
    [error]  10 != 2 (TestSpec.scala:19)
    [info] Total for specification TestMutableSpec
    [info] Finished in 121 ms
    [info] 1 example, 1 failure, 0 error