gpt4 book ai didi

unit-testing - Scalacheck 不会正确报告失败的情况

转载 作者:行者123 更新时间:2023-12-04 03:58:12 25 4
gpt4 key购买 nike

我写了以下规范

"An IP4 address" should "belong to just one class" in {
val addrs = for {
a <- Gen.choose(0, 255)
b <- Gen.choose(0, 255)
c <- Gen.choose(0, 255)
d <- Gen.choose(0, 255)
} yield s"$a.$b.$c.$d"

forAll (addrs) { ip4s =>
var c: Int = 0
if (IP4_ClassA.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassB.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassC.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassD.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassE.unapply(ip4s).isDefined) c = c + 1
c should be (1)
}
}

这在其范围内非常明确。

测试成功通过,但是当我强制它失败时(例如通过注释掉 if 语句之一)然后 ScalaCheck 正确报告错误,但消息没有正确提及用于评估命题的实际值。更具体地说,我得到:
[info] An IP4 address
[info] - should belong to just one class *** FAILED ***
[info] TestFailedException was thrown during property evaluation.
[info] Message: 0 was not equal to 1
[info] Location: (NetSpec.scala:105)
[info] Occurred when passed generated values (
[info] arg0 = "" // 4 shrinks
[info] )

在哪里可以看到 arg0 = "" // 4 shrinks不显示值。

我什至尝试添加一个简单的 println语句来审查案例,但输出似乎被修剪。我得到这样的东西
192.168.0.1
189.168.
189.
1

解决方案
import org.scalacheck.Prop.forAllNoShrink
import org.scalatest.prop.Checkers.check

"An IP4 address" should "belong to just one class" in {
val addrs = for {
a <- Gen.choose(0, 255)
b <- Gen.choose(0, 255)
c <- Gen.choose(0, 255)
d <- Gen.choose(0, 255)
} yield s"$a.$b.$c.$d"
check {
forAllNoShrink(addrs) { ip4s =>
var c: Int = 0
if (IP4.ClassA.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassB.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassC.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassD.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassE.unapply(ip4s).isDefined) c = c + 1
c == (1)
}
}
}

最佳答案

这是由 ScalaCheck 的测试用例简化功能引起的。 ScalaCheck 只是看到您的生成器生成一个字符串值。每当它发现一个值使您的属性为假时,它就会尝试简化该值。在您的情况下,它将它简化了四次,直到以空字符串结束,这仍然使您的属性为 false。

所以这是预期的,尽管令人困惑的行为。但是您可以通过三种不同的方式改善这种情况。

您可以选择其他数据结构来表示您的 IP 地址。这将使 ScalaCheck 能够以更智能的方式简化您的测试用例。例如,使用以下生成器:

val addrs = Gen.listOfN(4, Gen.choose(0,255))

现在 ScalaCheck 知道您的生成器只生成长度为 4 的列表,并且它只包含 0 到 255 之间的数字。测试用例简化过程将考虑到这一点,并且不会创建生成器无法生成的任何值开始。您可以改为在您的属性中转换为字符串。

第二种方法是直接向生成器添加过滤器,它告诉 ScalaCheck IP 地址字符串应该是什么样子。此过滤器在测试用例简化期间使用。定义一个检查有效字符串的函数,并以这种方式将其附加到现有的生成器:
def validIP(ip: String): Boolean = ...

val validAddrs = addrs.suchThat(validIP)

forAll(validAddrs) { ... }

第三种方法是使用 forAllNoShrink 简单地完全禁用测试用例简化功能。而不是 forAll :
Prop.forAllNoShrink(addrs) { ... }

我还应该提到,前两种方法需要 ScalaCheck 版本 >= 1.11.0 才能正常运行。

更新:
listOfN由于 https://github.com/rickynils/scalacheck/issues/89,收缩器实际上不再遵守列表长度.希望这可以在 ScalaCheck 的 future 版本中修复。

关于unit-testing - Scalacheck 不会正确报告失败的情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20037900/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com