如何为查找最小缺失正整数算法编写ScalaCheck生成器驱动属性测试
你可以通过抓取「找缺失最小正整数」算法的几个固有不变属性,来编写ScalaCheck生成器驱动测试,不需要依赖固定用例就能覆盖几乎所有场景。
前置准备
首先确保你的项目引入了ScalaCheck依赖,sbt配置示例:
libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.15.4" % Test
核心属性设计
我们一共可以定义4个互不重叠的验证属性,覆盖算法的所有正确性要求:
- 属性1:返回结果是正整数,最小必然是1
- 属性2:所有小于返回结果的正整数,都存在于输入序列的正整数中
- 属性3:返回结果本身,不存在于输入序列的正整数中
- 属性4:输入序列的顺序、重复值不影响返回结果
完整测试代码
import org.scalacheck.Properties import org.scalacheck.Prop.forAll import org.scalacheck.Gen import Solution.solution object SolutionCheck extends Properties("最小缺失正整数算法") { // 生成任意Int数组的生成器,ScalaCheck内置可直接用 property("返回结果必然为正整数,最小值为1") = forAll { arr: Array[Int] => val res = solution(arr) res >= 1 } property("所有小于返回值的正整数都存在于输入中") = forAll { arr: Array[Int] => val res = solution(arr) val posNums = arr.filter(_ > 0).toSet (1 until res).forall(posNums.contains) } property("返回值本身不存在于输入的正整数中") = forAll { arr: Array[Int] => val res = solution(arr) val posNums = arr.filter(_ > 0).toSet !posNums.contains(res) } property("数组顺序、重复值不影响计算结果") = forAll { arr: Array[Int] => val shuffledArr = scala.util.Random.shuffle(arr.toList).toArray val duplicatedArr = arr ++ arr solution(arr) == solution(shuffledArr) && solution(arr) == solution(duplicatedArr) } // 补充边界场景专属属性校验 property("全为非正整数的输入返回1") = forAll(Gen.choose(Int.MinValue, 0)) { num => solution(Array.fill(10)(num)) == 1 } property("连续1~N的正整数输入返回N+1") = forAll(Gen.posNum[Int]) { n => solution((1 to n).toArray) == n + 1 } }
运行说明
直接运行这个测试类,ScalaCheck会默认自动生成100组符合规则的随机测试用例,覆盖空数组、全负数、含零、含重复值、乱序正整数等各种场景,只要所有属性校验通过,你的实现就是正确的。
内容的提问来源于stack exchange,提问作者Shivam
相关产品推荐
相关产品推荐

