tribbloid
tribbloid

Reputation: 3858

In scalacheck + scalatest, is it possible to set randomisation seed for `Gen` WITHOUT sbt?

Assuming that in a Maven / Gradle project, a property-based test fails sporadically:

import org.scalacheck.Gen.Parameters
import org.scalacheck.rng.Seed
import org.scalacheck.{Arbitrary, Gen}
import org.scalatest.Assertion
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers._
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks

class MyTest extends AnyFlatSpec with ScalaCheckPropertyChecks {

  it should "work" in {

    implicit val arbString = Arbitrary(Gen.alphaStr)
    implicit val arb: Arbitrary[Foo] = Arbitrary(Gen.resultOf(Foo))

    forAll { f: Foo =>
      println(f)

      f.a shouldBe "1"
    }
  }
}

case class Foo(a: String, b: Int)

To reproduce a failed case, I try to override the random seed in the test case before the test was registered:

import org.scalacheck.Gen.Parameters
import org.scalacheck.rng.Seed
import org.scalacheck.{Arbitrary, Gen}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers._
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks

class MyTest extends AnyFlatSpec with ScalaCheckPropertyChecks {

  Gen.apply(Parameters.default, Seed.apply(12345L))

  it should "work" in {

    implicit val arbString = Arbitrary(Gen.alphaStr)
    implicit val arb: Arbitrary[Foo] = Arbitrary(Gen.resultOf(Foo))

    forAll { f: Foo =>
      println(f)

      f.a shouldBe "1"
    }
  }
}

case class Foo(a: String, b: Int)

But it is ineffective, ScalaCheck still use a random seed:

TestFailedException was thrown during property evaluation.
  Message: "[]" was not equal to "[1]"
  Location: (MyTest.scala:21)
  Occurred when passed generated values (
    arg0 = Foo("", 0)
  )
Init Seed: -8607081352353034494

Is this feature implemented or do I have to use something else?

Upvotes: 1

Views: 262

Answers (1)

Adrian
Adrian

Reputation: 5681

You're using the seed wrong. The correct way it to use a seed for each instance of Gen - not set a global seed.

Example:

import org.scalacheck.Gen.Parameters
import org.scalacheck.rng.Seed

case class Recommendation(..)

val recGen = Arbitrary.arbitrary[Recommendation]
val rec1=recGen.apply(Parameters.default, Seed.apply(12345L)).get
println(s"generated $rec1")

However I have seen examples where the seed is set globally but I have not tested that out:

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

The latest documentation on this is available at https://etorreborre.github.io/specs2/guide/SPECS2-4.3.4/org.specs2.guide.UseScalaCheck.html#working-with-seeds

Upvotes: 0

Related Questions