【问题标题】:Why do I get an empty list from Generator?为什么我从生成器中得到一个空列表?
【发布时间】:2017-12-02 08:21:26
【问题描述】:

我想测试我的功能并使用 ScalaCheck。

属性测试如下:

object WindowsSpec extends Properties("Windows") {


  val pathsGen = Gen.frequency(
    (3, "C:\\Windows\\DigitalLocker"),
    (2, "C:\\Temp"),
    (3, "Invalid folder"),
    (1, "C:\\Program Files\\Internet Explorer"),
    (4, "C:\\Program Files\\Windows Defender Advanced Threat Protection"),
    (1, "C:\\Program Files\\Windows Photo Viewer")
  )

  val pathsGenContainer = Gen.containerOf[List,String](pathsGen)

  property("validPaths") = forAll(pathsGenContainer) { a: List[String] =>
    println(a)
    Windows.arePathsValid(a).value.length > 0
  }

}

为什么我得到一个空列表?

我尝试在 shell 中找出生成器是否工作:

scala> :paste
// Entering paste mode (ctrl-D to finish)

  val pathsGen = Gen.frequency(
    (3, "C:\\Windows\\DigitalLocker"),
    (2, "C:\\Temp"),
    (3, "Invalid folder"),
    (1, "C:\\Program Files\\Internet Explorer"),
    (4, "C:\\Program Files\\Windows Defender Advanced Threat Protection"),
    (1, "C:\\Program Files\\Windows Photo Viewer")
  )

  val pathsGenContainer = Gen.containerOf[List,String](pathsGen)

// Exiting paste mode, now interpreting.

pathsGen: org.scalacheck.Gen[String] = org.scalacheck.Gen$$anon$1@6cb26245
pathsGenContainer: org.scalacheck.Gen[List[String]] = org.scalacheck.Gen$$anon$1@5335e968

scala> pathsGen
pathsGen   pathsGenContainer

scala> pathsGen.sample
res26: Option[String] = Some(C:\Program Files\Internet Explorer)

scala> pathsGen
   val pathsGen: org.scalacheck.Gen[String]

scala> pathsGenContainer.sample
res27: Option[List[String]] = Some(List(C:\Temp, C:\Temp, C:\Program Files\Windows Defender Advanced Threat Protection, Invalid folder, C:\Program Files\Internet Explorer, C:\Program Files\Internet Explorer, C:\Temp, C:\Temp, C:\Program Files\Windows Photo Viewer, Invalid folder, C:\Program Files\Windows Defender Advanced Threat Protection, C:\Program Files\Windows Defender Advanced Threat Protection, C:\Windows\DigitalLocker, Invalid folder, C:\Program Files\Windows Photo Viewer, C:\Program Files\Windows Defender Advanced Threat Protection, C:\Temp, C:\Program Files\Internet Explorer, C:\Temp, C:\Program Files\Windows Defender Advanced Threat Protection, C:\Program Files\Windows Photo Viewer, Invalid folder, Invalid folder, C:\Windows\DigitalLocker, C:\Program...

如您所见,生成器生成了一些输入。
我做错了什么?

【问题讨论】:

  • 您的代码看起来正确。我已将其复制粘贴到设置了 scalacheck 的项目中,并获得了生成路径的全屏)。我用过这样的检查: property("validPaths") = forAll(pathsGenContainer) { a: List[String] => println(a) a.forall(v => !v.isEmpty) }

标签: scala scalacheck


【解决方案1】:

TL;DR

pathsGenContainer 可以简化为Gen.listOf(pathsGen),所以我会参考它。它生成一个空列表是完全合理的。事实上,这是可取的,因为空列表是一种边缘情况,因此更有可能触发错误。如果你想要一个非空列表生成器,你可以使用Gen.nonEmptyListOfGen.nonEmptyContainerOf 来生成其他集合。

forAllsample 有什么不同?

您观察到在 REPL 中调用 sample 通常会生成一个非空列表,但运行您的 forAll 测试总是会生成一个空列表。区别如下:

  • forAll:当测试由框架运行时,它会以不同的属性运行多次,其中之一是size,它在可配置的范围内变化(默认为 [0 - 100])。 listOf 生成器具有大小感知能力,并将在每次测试中获取此属性。由于 0 是最小大小,因此始终会对其进行测试,并且您会得到一个空列表。
  • sample:您只手动调用了几次,并且没有传递任何属性。所以生成器只是生成一个随机列表。如果您一直调用sample,最终您得到一个空列表,但这不是确定性的。请注意,100% 随机数据对测试没有多大用处,我们始终希望确保我们也检查边缘情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    • 2020-05-09
    • 2021-06-24
    • 2023-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多