or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdexecution.mdindex.mdproperty-creation.mdtype-integration.md
tile.json

property-creation.mddocs/

Property Creation

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.

Capabilities

Basic Property Creation

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)}
"""
}

Multi-Parameter Properties

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))}
"""
}

Property Function Customization

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)
  }
"""
}

Context Management

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))
  }
"""
}

Types

// 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
}