Specs2 Result.foreach 可以像匹配器一样工作吗?

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

使用 Specs2,如果我这样做:

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

测试失败(如预期)

如果我这样做:

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

测试通过

对于 Result.foreach 我必须使用 and 使测试失败(如预期的那样):

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

这是为什么? 有没有办法让它以不那么令人惊讶的方式工作?这很容易出错 - 很容易就没有注意到有人没有输入 and

我检查了 Specs2 user guide,但没有提到我能找到的这种行为。

解决方法:将 AllExpectations 混入您的 Specification:

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

这会产生:

sbt> testOnly QuickStartSpec
[info] QuickStartSpec
[error] x foreach must fail
[error]  1 != 2 (QuickStartSpec.scala:8)

注意:我知道这不是 AllExpectations 特性的主要目的。然而,这似乎是一个明智的解决方案,因为 Result.foreach 的行为方式与可变规范中的匹配器不同。

此外,according to the docs, the goal of "unit specifications" is to let users have multiple expectations per example without the need to use and. In light of this, the behavior of Result.foreach indeed seems misleading. If you think this is a bug, you may consider opening an issue

这可能应该得到更好的记录。 Result.foreach 函数确实应该是无副作用的。如果你想要副作用,你可以直接在你的规范中调用 foreach 因为这个是用可变规范的“抛出”行为连接的:

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