重现ScalaCheck测试运行

时间:2014-02-02 07:38:53

标签: scalacheck

这被问到https://stackoverflow.com/questions/12639454/make-scalacheck-tests-deterministic中的“红利问题”,但没有回答:

有没有办法打印出ScalaCheck使用的随机种子,以便您可以重现特定的测试运行?

一种hacky方式:包装一个随机生成器,在初始化时打印其种子并将其传递给Test.Parameters。有更好的选择吗?

3 个答案:

答案 0 :(得分:2)

今天没有办法做到这一点。但是,它将在未来实施,请参阅https://github.com/rickynils/scalacheck/issues/67

答案 1 :(得分:2)

到目前为止,这是可能的(请参阅scalacheck#263)。 这里有一些很好的示例:Simple example of using seeds with ScalaCheck for deterministic property-based testing

简而言之,您可以这样做:

propertyWithSeed("your property", Some("seed")) =
  forAll { ??? }

,当此属性失败时,将打印种子。

答案 2 :(得分:1)

这是我的答案there

  

奖励问题:是否有官方方法可以打印出ScalaCheck使用的随机种子,以便您甚至可以重现不确定的测试运行?

specs2-scalacheck版本4.6.0开始,这现在是默认行为:

给出测试文件HelloSpec

package example

import org.specs2.mutable.Specification
import org.specs2.ScalaCheck

class HelloSpec extends Specification  with ScalaCheck {
package example

import org.specs2.mutable.Specification
import org.specs2.ScalaCheck

class HelloSpec extends Specification  with ScalaCheck {
  s2"""
    a simple property       $ex1
  """

  def ex1 = prop((s: String) => s.reverse.reverse must_== "")
}

build.sbt配置:

import Dependencies._

ThisBuild / scalaVersion     := "2.13.0"
ThisBuild / version          := "0.1.0-SNAPSHOT"
ThisBuild / organization     := "com.example"
ThisBuild / organizationName := "example"

lazy val root = (project in file("."))
  .settings(
    name := "specs2-scalacheck",
    libraryDependencies ++= Seq(
      specs2Core,
      specs2MatcherExtra,
      specs2Scalacheck
    ).map(_ % "test")
  )

project/Dependencies

import sbt._

object Dependencies {
  lazy val specs2Core                       = "org.specs2"             %% "specs2-core"               % "4.6.0"
  lazy val specs2MatcherExtra               = "org.specs2"             %% "specs2-matcher-extra"      % specs2Core.revision
  lazy val specs2Scalacheck                 = "org.specs2"             %% "specs2-scalacheck"         % specs2Core.revision

}

sbt控制台运行测试时:

sbt:specs2-scalacheck> testOnly example.HelloSpec

您将获得以下输出:

[info] HelloSpec
[error]     x a simple property
[error]  Falsified after 2 passed tests.
[error]  > ARG_0: "\u0000"
[error]  > ARG_0_ORIGINAL: "猹"
[error]  The seed is X5CS2sVlnffezQs-bN84NFokhAfmWS4kAg8_gJ6VFIP=
[error]  
[error]  > '' != '' (HelloSpec.scala:11)
[info] Total for specification HelloSpec

要重现特定的运行(即具有相同的种子),您可以从输出中获取seed,并使用命令行scalacheck.seed传递它:

sbt:specs2-scalacheck>testOnly example.HelloSpec -- scalacheck.seed X5CS2sVlnffezQs-bN84NFokhAfmWS4kAg8_gJ6VFIP=

这将产生与以前相同的输出。

您还可以使用setSeed以编程方式设置种子:

def ex1 = prop((s: String) => s.reverse.reverse must_== "").setSeed("X5CS2sVlnffezQs-bN84NFokhAfmWS4kAg8_gJ6VFIP=")

提供Seed的另一种方法是传递设置Parameters的隐式seed

package example

import org.specs2.mutable.Specification
import org.specs2.ScalaCheck
import org.scalacheck.rng.Seed
import org.specs2.scalacheck.Parameters

class HelloSpec extends Specification  with ScalaCheck {

  s2"""
    a simple property       $ex1
  """

  implicit val params = Parameters(minTestsOk = 1000, seed = Seed.fromBase64("X5CS2sVlnffezQs-bN84NFokhAfmWS4kAg8_gJ6VFIP=").toOption)

  def ex1 = prop((s: String) => s.reverse.reverse must_== "")
}

Here是有关所有这些各种方式的文档。 这个blog也谈到了这一点。