在ScalaCheck中表示没有丢弃评估的属性

时间:2016-05-24 11:24:17

标签: scala scalacheck

鉴于此:

  property("Empty range") {
    forAll { (min: Int, max: Int) =>
      whenever (min == max) {
        Range(min, max).size should be (0)
      }
    }
  }

我得到了

[info] - Empty range *** FAILED *** 
[info]   Gave up after 5 successful property evaluations. 96 evaluations were discarded.

我如何表达我的测试用例,即捕获不管ab的Range的属性,如果它们相等,那么Range(a,b)应为空。< / p>

另一个:

  property("10 long range") {
    forAll { (min: Int, max: Int) =>
      whenever (min < max && (max.toLong-min.toLong).abs == 10) {
        Range(min, max).head should be (min)
      }
    }
  }

我有一堆像这样的测试用例(类似于Range的类),所有这些都失败并出现相同的错误。

我想捕获具有给定大小的Ranges,并测试该范围内的元素 - 我希望ScalaCheck为我生成范围边界。

1 个答案:

答案 0 :(得分:1)

对于迟到的回复感到抱歉,但是,对于您的第一种情况,由于您只是测试两个匹配值的范围是0,您只需要生成一个值:

property("Empty range") {
  forAll { x: Int =>
    Range(x, x).size should be (0)
  }
}

通过对此测试使用whenever案例,生成两个相等值的概率非常低,因此您将浪费min&amp;的许多组合。 max不平等。最终,它会放弃尝试找到满足条件的组合。上面的替代方法适用于每个生成的值,因此它也更有效。

第二个例子是类似的。首先,将丢弃min为&gt; = max的所有情况。然后,将丢弃两个值之间的差异不是10的所有情况。因此,再一次,生成比min值正好小10 max值的机会非常低,以至于测试将放弃尝试查找满足此条件的值。同样,以下内容等同于您所拥有的内容,并且将对大多数生成的值起作用(只需要丢弃最大值10以内的值,以避免在添加时出现溢出)。

property("10 long range") {
  forAll { x: Int =>
    whenever (x <= Int.MaxValue - 10) {
      Range(x, x + 10).head should be (min)
    }
  }
}

但是,您的测试似乎有点不寻常,因为您正在测试一些非常具体的情况,而您应该寻找更一般的条件。例如:

property("Range size") {
  forAll { (min: Int, max: Int) =>
    whenever (min <= max && (max.toLong - min.toLong) <= Int.MaxValue) {
      Range(min, max).size should be (max - min)
    }
  }
}

应涵盖所有大小比较,包括两个值相等且大小为0的情况。(在这种情况下,whenever子句是必需的,以防止min值高于max值并确保范围大小不超过Int的容量。您也可以编写此测试,在生成的数字方面稍微更有效,如下所示:

property("Range size #2") {
  forAll { (a: Int, b: Int) =>
    whenever (Math.abs(a.toLong - b.toLong) <= Int.MaxValue) {
      val min = Math.min(a, b)
      val max = Math.max(a, b)
      Range(min, max).size should be (max - min)
    }
  }
}

在上述两种情况下,whenever条款偶尔会失败 - 特别是在后一种情况下 - 而不是几乎所有时间。