Create property-based tests from functions with automatic test case generation, shrinking of counterexamples, and statistical data collection. The property creation system supports functions with 1-8 parameters and provides extensive customization options for generators, shrinkers, and data collectors.
Create properties from functions using automatic type class derivation for generators, shrinkers, and pretty printers.
def prop[T, R](result: T => R)(implicit
arbitrary: Arbitrary[T],
shrink: Shrink[T],
pretty: T => Pretty,
prettyFreqMap: FreqMap[Set[Any]] => Pretty,
asResult: AsResult[R],
parameters: Parameters
): ScalaCheckFunction1[T, R]Usage:
import org.specs2._
import org.specs2.ScalaCheck
class StringSpec extends Specification with ScalaCheck { def is = s2"""
String length property ${prop((s: String) => s.length >= 0)}
List reverse property ${prop((xs: List[Int]) => xs.reverse.reverse == xs)}
"""
}Create properties from functions with multiple parameters, supporting up to 8 arguments with individual type class instances for each parameter.
def prop[T1, T2, R](result: (T1, T2) => R)(implicit
arbitrary1: Arbitrary[T1], shrink1: Shrink[T1], pretty1: T1 => Pretty,
arbitrary2: Arbitrary[T2], shrink2: Shrink[T2], pretty2: T2 => Pretty,
prettyFreqMap: FreqMap[Set[Any]] => Pretty,
asResult: AsResult[R],
parameters: Parameters
): ScalaCheckFunction2[T1, T2, R]
def prop[T1, T2, T3, R](result: (T1, T2, T3) => R)(implicit ...): ScalaCheckFunction3[T1, T2, T3, R]
def prop[T1, T2, T3, T4, R](result: (T1, T2, T3, T4) => R)(implicit ...): ScalaCheckFunction4[T1, T2, T3, T4, R]
def prop[T1, T2, T3, T4, T5, R](result: (T1, T2, T3, T4, T5) => R)(implicit ...): ScalaCheckFunction5[T1, T2, T3, T4, T5, R]
def prop[T1, T2, T3, T4, T5, T6, R](result: (T1, T2, T3, T4, T5, T6) => R)(implicit ...): ScalaCheckFunction6[T1, T2, T3, T4, T5, T6, R]
def prop[T1, T2, T3, T4, T5, T6, T7, R](result: (T1, T2, T3, T4, T5, T6, T7) => R)(implicit ...): ScalaCheckFunction7[T1, T2, T3, T4, T5, T6, T7, R]
def prop[T1, T2, T3, T4, T5, T6, T7, T8, R](result: (T1, T2, T3, T4, T5, T6, T7, T8) => R)(implicit ...): ScalaCheckFunction8[T1, T2, T3, T4, T5, T6, T7, T8, R]Usage:
class ArithmeticSpec extends Specification with ScalaCheck { def is = s2"""
Addition commutativity ${prop((a: Int, b: Int) => a + b == b + a)}
String concatenation ${prop((s1: String, s2: String, s3: String) =>
(s1 + s2) + s3 == s1 + (s2 + s3))}
"""
}Customize property functions with custom generators, shrinkers, pretty printers, data collectors, and execution contexts.
// Single parameter property functions
trait ScalaCheckFunction1[T, R] extends ScalaCheckFunction {
def noShrink: ScalaCheckFunction1[T, R]
def setArbitrary(arbitrary: Arbitrary[T]): ScalaCheckFunction1[T, R]
def setGen(gen: Gen[T]): ScalaCheckFunction1[T, R]
def setShrink(shrink: Shrink[T]): ScalaCheckFunction1[T, R]
def setPretty(pretty: T => Pretty): ScalaCheckFunction1[T, R]
def pretty(pretty: T => String): ScalaCheckFunction1[T, R]
def collect: ScalaCheckFunction1[T, R]
def collectArg(f: T => Any): ScalaCheckFunction1[T, R]
def prepare(action: T => T): ScalaCheckFunction1[T, R]
def setContext(context: Context): ScalaCheckFunction1[T, R]
}
// Multi-parameter property functions (similar pattern for 2-8 parameters)
trait ScalaCheckFunction2[T1, T2, R] extends ScalaCheckFunction {
def noShrink: ScalaCheckFunction2[T1, T2, R]
def setArbitrary1(a1: Arbitrary[T1]): ScalaCheckFunction2[T1, T2, R]
def setArbitrary2(a2: Arbitrary[T2]): ScalaCheckFunction2[T1, T2, R]
def setArbitraries(a1: Arbitrary[T1], a2: Arbitrary[T2]): ScalaCheckFunction2[T1, T2, R]
def setGen1(g1: Gen[T1]): ScalaCheckFunction2[T1, T2, R]
def setGen2(g2: Gen[T2]): ScalaCheckFunction2[T1, T2, R]
def setGens(g1: Gen[T1], g2: Gen[T2]): ScalaCheckFunction2[T1, T2, R]
def setShrink1(s1: Shrink[T1]): ScalaCheckFunction2[T1, T2, R]
def setShrink2(s2: Shrink[T2]): ScalaCheckFunction2[T1, T2, R]
def setShrinks(s1: Shrink[T1], s2: Shrink[T2]): ScalaCheckFunction2[T1, T2, R]
def setPretty1(p1: T1 => Pretty): ScalaCheckFunction2[T1, T2, R]
def setPretty2(p2: T2 => Pretty): ScalaCheckFunction2[T1, T2, R]
def pretty1(p1: T1 => String): ScalaCheckFunction2[T1, T2, R]
def pretty2(p2: T2 => String): ScalaCheckFunction2[T1, T2, R]
def setPretties(p1: T1 => Pretty, p2: T2 => Pretty): ScalaCheckFunction2[T1, T2, R]
def pretties(p1: T1 => String, p2: T2 => String): ScalaCheckFunction2[T1, T2, R]
def collectArg1(f: T1 => Any): ScalaCheckFunction2[T1, T2, R]
def collectArg2(f: T2 => Any): ScalaCheckFunction2[T1, T2, R]
def collect1: ScalaCheckFunction2[T1, T2, R]
def collect2: ScalaCheckFunction2[T1, T2, R]
def collectAllArgs(f1: T1 => Any, f2: T2 => Any): ScalaCheckFunction2[T1, T2, R]
def collectAll: ScalaCheckFunction2[T1, T2, R]
def prepare(action: (T1, T2) => (T1, T2)): ScalaCheckFunction2[T1, T2, R]
}Usage:
class CustomGeneratorSpec extends Specification with ScalaCheck { def is = s2"""
Custom generator property ${
prop((n: Int) => n >= 0)
.setGen(Gen.choose(0, 1000))
.noShrink
.collect
}
Custom shrinking property ${
prop((s: String) => s.nonEmpty)
.setGen(Gen.alphaStr.suchThat(_.nonEmpty))
.pretty(s => s"String: '$s'")
.collectArg(_.length)
}
"""
}Add setup/teardown operations around property execution using execution contexts.
trait ScalaCheckFunction extends ScalaCheckProperty {
def context: Option[Context]
def setContext(context: Context): SelfType
def before(action: =>Any): SelfType
def after(action: =>Any): SelfType
def beforeAfter(beforeAction: =>Any, afterAction: =>Any): SelfType
def around(action: Result => Result): SelfType
}Usage:
class ContextSpec extends Specification with ScalaCheck { def is = s2"""
Property with setup ${
prop((data: List[Int]) => processData(data).nonEmpty)
.before(initializeSystem())
.after(cleanupSystem())
}
Property with around context ${
prop((input: String) => validateInput(input))
.around((result: Result) => withDatabase(result))
}
"""
}// Property creation trait
trait ScalaCheckPropertyCreation {
def prop[T, R](result: T => R)(implicit ...): ScalaCheckFunction1[T, R]
def prop[T1, T2, R](result: (T1, T2) => R)(implicit ...): ScalaCheckFunction2[T1, T2, R]
// ... up to 8 parameters
}
// Base property function trait
trait ScalaCheckFunction extends ScalaCheckProperty {
def noShrink: SelfType
def context: Option[Context]
def setContext(context: Context): SelfType
def before(action: =>Any): SelfType
def after(action: =>Any): SelfType
def beforeAfter(beforeAction: =>Any, afterAction: =>Any): SelfType
def around(action: Result => Result): SelfType
}
// Type class instances container
case class ScalaCheckArgInstances[T](
arbitrary: Arbitrary[T],
shrink: Option[Shrink[T]],
collectors: List[T => Any],
pretty: T => Pretty
) {
def collect(t: T, p: Prop): Prop
}