ScalaTest如何校验序列所有元素匹配谓词并获得友好报错提示
ScalaTest 全序列元素谓词校验的友好报错实现
现有写法的痛点
直接调用集合的forall方法拿到布尔结果后做相等断言,会丢失所有校验过程的上下文信息。
示例代码:
it should "check that items satisfy predicate" in { List(1,2,3,4,5,6).forall(x => x < 5) should equal (true) }
这类写法执行失败时,只会输出无排查价值的提示:"false did not equal true",既无法定位哪个元素未满足谓词,也无法获知不匹配的具体细节,对自定义逻辑的校验场景尤其不友好。
优化实现方案
- 使用ScalaTest内置的检查器匹配能力替代手动布尔断言。这类能力会在遍历元素的过程中记录每一步的校验结果,失败时自动输出带上下文的提示,明确标注不满足条件的元素位置、元素值。
针对大小比较类的谓词,可直接使用简写匹配:
上述代码失败时会输出类似提示:// 引入对应匹配能力依赖 import org.scalatest.matchers.should.Matchers._ import org.scalatest.Inspectors._ it should "check that items satisfy predicate" in { all (List(1,2,3,4,5,6)) should be < 5 }All elements of List(1, 2, 3, 4, 5, 6) satisfied the predicate, but 5 at index 4 did not, and 6 at index 5 did not,可直接定位异常元素。 - 针对任意自定义谓词的校验场景,可结合
forAll检查器封装自定义判断逻辑,而非预先计算全局布尔结果。
示例代码:
这种写法的失败提示同样会标注具体异常元素的位置和值,不会出现无意义的布尔比对结果。// 自定义任意校验逻辑:判断值是否为小于5的偶数 def smallEvenCheck(x: Int): Boolean = x < 5 && x % 2 == 0 it should "check that items satisfy custom predicate" in { forAll (List(1,2,3,4,5,6)) { element => smallEvenCheck(element) shouldBe true } } - 避免使用
集合forall(谓词) should equal true这类压缩校验过程的写法,这类写法会把集合遍历、元素判断的所有细节全部隐去,只保留最终的布尔值,天然不具备输出友好报错的能力。
内容的提问来源于stack exchange,提问作者Andrey Golikov
相关产品推荐
相关产品推荐

