0

我在 ScalaTest 上进行基于属性的测试,我有以下代码:

val myStrings = Gen.oneOf("hi", "hello")
forAll(myStrings) { s: String =>
  println(s"String tested: $s")
}

当我运行forAll代码时,我注意到多次尝试相同的值,例如

String tested: hi
String tested: hello
String tested: hi
String tested: hello
String tested: hi
String tested: hello
...

鉴于上面的代码,我想知道是否有办法让每个值oneOf只尝试一次。换句话说,要让 ScalaTest 不要两次使用相同的值。

即使我使用了其他生成器,例如Gen.alphaStr,我也想找到一种方法来避免两次测试相同的字符串。我对此感兴趣的原因是因为每个测试都针对在不同进程中运行的服务器运行,因此涉及一些成本,所以我想避免两次测试相同的东西。

4

2 回答 2

0

我的目标是增加值的熵。使用随机句子会增加很多,尽管(理论上)不能解决问题。

val genWord = Gen.onOf("hi", "hello")

def sentanceOf(words: Int): Gen[String] = {
   Gen.listOfN(words, genWord).map(_.mkString(" ")
}
于 2016-10-20T09:00:24.863 回答
0

你试图做的似乎是反对 scalacheck 意识形态(见注1);但是通过减少样本数量是有可能的(很有可能):

scala> forAll(oneOf("a", "b")){i => println(i); true}.check(Test.Parameters.default.withMinSuccessfulTests(2))
a
b
+ OK, passed 2 tests.

请注意,有时您仍然可以获得 aa/bb,因为 scala-check 是建立在随机性和统计方法上的。如果您需要始终检查所有组合 - 您可能不需要 scala-check:

scala> assert(Set("a", "b").forall(_ => true))

基本上Gen允许您创建一个表示输入值分布的无限集合。您生成的值越多 - 您获得的采样就越好。因此,如果您有 N 个可能的状态,则不能保证它们不会在无限集合中重复。

通常你将几个 generator/props 组合在一起,所以withMinSuccessfulTests会影响所有它们,这对于测试配置非常方便(你可以选择你的 sample 的 size 以获得更好的性能)。

Note1) 需要什么 scalacheck 才能将组合数量从最大值(大于 100)减少到仍然可以很好地检查的某个值。因此,当一组可能的输入非常庞大时,scalacheck 很有用。在那种情况下,重复的概率真的很小

PS谈论oneOf(来自scaladoc):

def oneOf[T](t0: T, t1: T, tn: T*): Gen[T]

从列表中选择一个随机值

另请参阅(示例有点过时):如何减少 ScalaCheck 生成的测试用例的数量?

于 2016-10-20T08:51:27.537 回答