将 foreach 转换为包含 forall 匹配器

Converting a foreach into contains forall matcher

我在规范中有以下表达式,目的是确保每个元素的值 distanceToEnd 非常接近其后元素的 distanceFromPrevious 值的总和.

foo.tails.foreach {
  case h +: t => h.distanceToEnd.miles must
    beCloseTo(t.map(_.distanceFromPrevious.miles).sum, 10e-10)
  case _ => ok
}

理想情况下,这应该采用 foo.tails must contain { ... }.forall 的形式,但我无法理解如何为 contains 创建必要的 ValueCheck 参数。我将如何转换这个特定示例?

如果在使用任何 specs2 匹配器之前计算 distanceFromPrevious 的部分和并减去 distanceToEnd,则可以使用 forall。那么就可以只用beCloseTo matchers中的一个与0进行比较,如下:

foo.tail.scanRight(0.0)(_.distanceFromPrevious.miles + _).init  // calculate partial sums of previous distances
    .zip(foo.init.map(_.distanceToEnd.miles))                   // combine with end distances
    .map(t => t._1 - t._2)                                      // take difference of summed and end distances
    .must(contain(be ~(0.0 +/- 10e-10)).forall)                 // all differences should be effectively 0

不幸的是,类型推断不适用于部分函数,​​因此您需要显式匹配:

 foo.tails must contain { ts: List[Foo] =>
   ts match {
     case h +: t => h.distanceToEnd.miles must
       beCloseTo(t.map(_.distanceFromPrevious.miles).sum, 10e-10)
     case _ => ok
   }
}.forall