ScalaCheck integration
Weaver comes with basic ScalaCheck integration, allowing for property-based testing.
Installation
You'll need to install an additional dependency in order to use ScalaCheck with Weaver.
SBT
libraryDependencies += "org.typelevel" %% "weaver-scalacheck" % "0.13.0" % Test
Mill
object test extends Tests {
def ivyDeps = Agg(
ivy"org.typelevel::weaver-scalacheck:0.13.0"
)
}
Usage
Add the weaver.scalacheck.Checkers mixin to use ScalaCheck within your test suite.
import org.scalacheck.Gen
import weaver._
import weaver.scalacheck._
object ForallExamples extends SimpleIOSuite with Checkers {
// CheckConfig can be overridden at the suite level
override def checkConfig: CheckConfig =
super.checkConfig.copy(perPropertyParallelism = 100)
// Using a single `Gen` instance
test("Single Gen form") {
// Takes a single, explicit `Gen` instance
forall(Gen.posNum[Int]) { a =>
expect(a > 0)
}
}
// There is only one overload for the `forall` that takes an explicit `Gen` parameter
// To use multiple `Gen` instances, compose them monadically before passing to `forall`
test("Multiple Gen form") {
// Compose into a single `Gen[(Int, Int)]`
val gen = for {
a <- Gen.posNum[Int]
b <- Gen.posNum[Int]
} yield (a, b)
// Unapply the tuple to access individual members
forall(gen) { case (a, b) =>
expect(a > 0) and expect(b > 0)
}
}
// Using a number of `Arbitrary` instances
test("Arbitrary form") {
// There are 6 overloads, to pass 1-6 parameters
forall { (a1: Int, a2: Int, a3: Int) =>
expect(a1 * a2 * a3 == a3 * a2 * a1)
}
}
test("Failure example") {
// There are 6 overloads, to pass 1-6 parameters
forall { (a1: Int, a2: Int) =>
expect(a1 + a2 % 2 == 0)
}
}
test("CheckConfig at test level") {
// CheckConfig can be overridden locally at the test level
forall.withConfig(CheckConfig.default.copy(perPropertyParallelism = 1)) {
(x: Int) => expect(x > 0)
}
}
}
ForallExamples + Single Gen form 79ms + Multiple Gen form 51ms + Arbitrary form 122ms - Failure example 17ms - CheckConfig at test level 7ms *************FAILURES************* ForallExamples - Failure example 17ms
[0] Property test failed on try 1 with input:
[0] 1074126039
[0] 902381761
[0] You can reproduce this by adding the following configuration to your test:
[0]
[0] forall.withConfig(checkConfig.withInitialSeed(org.scalacheck.rng.Seed.fromBase64("EOib7Kql-xF1s2m95kOgjt_g-aORIKwtbtAYpGre4HK=").toOption))
[0]
[0] scalacheck.md#L56
[0] forall { (a1: Int, a2: Int) =>
[0] ^
[1] assertion failed
[1]
[1] expect(a1 + a2 % 2 == 0)
[1]
[1] Use the `clue` function to troubleshoot
[1]
[1] scalacheck.md#L57
[1] expect(a1 + a2 % 2 == 0)
[1] ^ - CheckConfig at test level 7ms
[0] Property test failed on try 1 with input:
[0] -795515619
[0] You can reproduce this by adding the following configuration to your test:
[0]
[0] forall.withConfig(checkConfig.withInitialSeed(org.scalacheck.rng.Seed.fromBase64("yzZ0xb1fX0aqbYC3rATUPicsCP066WRMXMjE4ESDp8M=").toOption))
[0]
[0] scalacheck.md#L63
[0] forall.withConfig(CheckConfig.default.copy(perPropertyParallelism = 1)) {
[0] ^
[1] assertion failed
[1]
[1] expect(x > 0)
[1]
[1] Use the `clue` function to troubleshoot
[1]
[1] scalacheck.md#L64
[1] (x: Int) => expect(x > 0)
[1] ^ Total 5, Failed 2, Passed 3, Ignored 0