ScalaCheck Effect is a library that extends the functionality of ScalaCheck to support "effectful" properties. An effectful property is one that evaluates each sample in some type constructor F[_]. For example:
import org.scalacheck.effect.PropF
import org.scalacheck.Test
import cats.effect.{ExitCode, IO, IOApp}
object Example extends IOApp {
def run(args: List[String]): IO[ExitCode] = {
val p: PropF[IO] =
PropF.forAllF { (x: Int) =>
IO(x).map(res => assert(res == x))
}
val result: IO[Test.Result] = p.check()
result.flatMap(r => IO(println(r))).as(ExitCode.Success)
}
}Running this program results in the output: Result(Passed,100,0,Map(),0).
This library provides the org.scalacheck.effect.PropF type, which is the effectul analog to org.scalacheck.Prop. In this example, we use PropF.forAllF to write a property of the shape Int => IO[Unit]. This example uses cats.effect.IO as the type constructor, but any effect F[_] with an instance of MonadError[F, Throwable] can be used, including scala.concurrent.Future.
The key idea here is using the PropF.{forAllF, forAllNoShrinkF} methods to create PropF[F] instances. The check() method on PropF converts a PropF[F] to a F[Test.Result].
libraryDependencies += "org.typelevel" %% "scalacheck-effect" % scalacheckEffectVersionThis project also provides support for checking PropF values from within MUnit based test suites. To use scalacheck-effect with munit, add the following dependency to your build:
libraryDependencies += "org.typelevel" %% "scalacheck-effect-munit" % scalacheckEffectVersion % Testimport munit.{CatsEffectSuite, ScalaCheckEffectSuite}
import org.scalacheck.effect.PropF
// Example uses https://github.com/typelevel/munit-cats-effect
class ExampleSuite extends CatsEffectSuite with ScalaCheckEffectSuite {
test("first PropF test") {
PropF.forAllF { (x: Int) =>
IO(x).start.flatMap(_.join).map(res => assert(res == x))
}
}
}- Support effectful properties without blocking.
- Compatibility with
Gen/Cogen/Arbitrary. - Parity with
Propfeatures, including shrinking. - Follow same style as ScalaCheck and use ScalaCheck reporting.
- Integrate well with popular test frameworks.
- Non-goal: provide direct support for checking effectful properties directly from SBT or from standalone app.
Calling Await.result, unsafeRunSync() or a similar blocking operation is not possible on Scala.js.
This library builds heavily on the ideas in ScalaCheck. It grew out of the FS2 AsyncPropertySuite, which only implemented a handful of features. The Weaver Test framework also has similar support for effectful properties. Finally, the Scala Hedgehog library has a prototype of similar functionality.