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
QuickCheck is the original property-based testing library (qc-hackage). This skill covers both:
-- In .cabal:
build-depends: QuickCheck >= 2.18
-- In stack.yaml: add 'QuickCheck' to extra-deps if not in resolver// build.sbt
libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.18.0" % Test
// For ScalaTest integration:
libraryDependencies += "org.scalatest" %% "scalatest-propspec" % "3.2.18" % TestPinned versions and update notes: references/quickcheck-reference.md.
import Test.QuickCheck
prop_reverseInvolutive :: [Int] -> Bool
prop_reverseInvolutive xs = reverse (reverse xs) == xs
main :: IO ()
main = quickCheck prop_reverseInvolutivequickCheck runs the property with 100 random [Int] values by
default; on failure, prints the failing case + the shrunk minimal
example.
For ghci:
ghci> quickCheck prop_reverseInvolutive
+++ OK, passed 100 tests.Define an Arbitrary instance with arbitrary (the generator) and
shrink (which returns simpler candidates for minimizing a failure):
data User = User { userId :: Int, userEmail :: String, userAge :: Int }
deriving (Show, Eq)
instance Arbitrary User where
arbitrary = do
uid <- arbitrary `suchThat` (> 0)
name <- listOf1 (elements ['a'..'z'])
age <- choose (18, 100)
return $ User uid (name ++ "@example.com") age
shrink (User i e a) =
[ User i' e a | i' <- shrink i, i' > 0 ] ++
[ User i e a' | a' <- shrink a, a' >= 18, a' <= 100 ]The QuickCheck module map (Test.QuickCheck.Gen, .Arbitrary,
.Function, .Monadic):
references/quickcheck-reference.md.
==> is conditional implication - discard cases where the
precondition fails:
-- Conditional property: discard cases where xs is empty
prop_headOfNonEmpty :: [Int] -> Property
prop_headOfNonEmpty xs = not (null xs) ==> head xs == xs !! 0forAll (inline quantification) and classify / label
(distribution tracking):
references/quickcheck-reference.md.
import org.scalacheck._
import org.scalacheck.Prop.forAll
object UserSpecification extends Properties("User") {
implicit val userGen: Arbitrary[User] = Arbitrary {
for {
id <- Gen.posNum[Int]
name <- Gen.alphaLowerStr.suchThat(_.length >= 3)
age <- Gen.choose(18, 100)
} yield User(id, s"$name@example.com", age)
}
property("json round-trip") = forAll { (u: User) =>
val json = encode(u)
decode[User](json) == Right(u)
}
property("sorted list stays sorted") = forAll { (xs: List[Int]) =>
val sorted = xs.sorted
sorted == sorted.sorted
}
}Same shape as Haskell QuickCheck; Prop.forAll is the equivalent
of quickCheck. ScalaTest integration (AnyPropSpec +
ScalaCheckPropertyChecks):
references/quickcheck-reference.md.
Haskell:
import Test.QuickCheck
main = quickCheckWith (stdArgs { maxSuccess = 1000, maxSize = 100 }) prop_X
-- or:
quickCheckWith (stdArgs { maxSuccess = 100, maxSize = 50, maxDiscardRatio = 10 }) prop_XScala:
import org.scalacheck.Test
import org.scalacheck.Prop
val params = Test.Parameters.default
.withMinSuccessfulTests(1000)
.withMaxDiscardRatio(10.0f)Haskell with cabal:
cabal testScala with sbt:
sbt testFor deterministic CI, set the seed:
quickCheckWith (stdArgs { replay = Just (mkQCGen 42, 0) }) prop_Xval params = Test.Parameters.default.withInitialSeed(rng.Seed(42L))quickCheck,
Property type, Arbitrary typeclass, shrink, Test.QuickCheck.*
modules.scalacheck.org) - Scala port; same
conceptual model, JVM ecosystem.hypothesis-testing,
fast-check-testing,
proptest-testing,
jqwik-testing - all inspired by
QuickCheck; per-language siblings.