Authors property-based tests for Haskell using QuickCheck (the original PBT library) and for Scala via ScalaCheck (the JVM port) - wires `quickCheck` (Haskell) / `forAll` (ScalaCheck) drivers, defines `Arbitrary` instances or generators, uses `shrink` to find minimal counterexamples, and integrates with HSpec / Tasty (Haskell) or specs2 / ScalaTest. Use when the codebase is Haskell or Scala and the team wants the canonical PBT library that the entire family (Hypothesis / fast-check / proptest / jqwik) was inspired by.
74
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Detailed lookup material for quickcheck-testing. Sources:
QuickCheck on Hackage, ScalaCheck (scalacheck.org).
2.18.0.0 latest stable at source-fetch (build-depends: QuickCheck >= 2.18).1.18.0; ScalaTest-plus integration via scalatest-propspec 3.2.18.Check the sources before bumping.
| Module | Use |
|---|---|
Test.QuickCheck | Main entry: quickCheck, verboseCheck. |
Test.QuickCheck.Arbitrary | Arbitrary typeclass for custom types. |
Test.QuickCheck.Gen | Custom generators. |
Test.QuickCheck.Function | Function generation. |
Test.QuickCheck.Monadic | "for testing stateful/monadic code" (qch). |
-- Quantify per-test scope
prop_sortIdempotent :: Property
prop_sortIdempotent = forAll (listOf1 arbitrary :: Gen [Int]) $ \xs ->
sort (sort xs) == sort xs
-- Classify cases for distribution monitoring
prop_lengthClassified :: [Int] -> Property
prop_lengthClassified xs = classify (null xs) "empty" $
classify (length xs > 100) "large" $
length (reverse xs) == length xsforAll quantifies inline; classify / label track distribution.
import org.scalatest.propspec.AnyPropSpec
import org.scalatest.matchers.should.Matchers
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
class UserPropSpec extends AnyPropSpec with Matchers with ScalaCheckPropertyChecks {
property("reverse is involutive") {
forAll { (xs: List[Int]) =>
xs.reverse.reverse shouldBe xs
}
}
}| Anti-pattern | Why it fails | Fix |
|---|---|---|
Skipping shrink in custom Arbitrary | Failures aren't shrunk; counterexample messages are huge. | Always implement shrink (Step 4). |
Heavy ==> (Haskell) / suchThat (Scala) preconditions | Cases discarded; "Gave up after N tests" warning. | Restructure the generator to produce only valid inputs (Step 4-5). |
arbitrary without Arbitrary typeclass instance for custom types | Compile error / runtime "no instance" - must define instance per type. | Define Arbitrary T instance (Step 4). |
| Random seed in CI | Failures hard to reproduce. | Fixed seed (Step 8). |
quickCheck from Main | Mixes test code with executable. | Use HSpec / Tasty (Haskell) or ScalaTest (Scala) for organization. |
| Properties that always pass trivially | No actual verification; false confidence. | verboseCheck to see distribution; reformulate. |
fc.scheduler,
basic QuickCheck doesn't model concurrent interleavings.shrink implementations need
care to terminate.