CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-scalacheck--scalacheck-2-12

A comprehensive property-based testing library for Scala and Java applications that enables developers to specify program properties as testable assertions and automatically generates test cases to verify these properties.

Pending
Overview
Eval results
Files

test-execution.mddocs/

Test Execution

The ScalaCheck test execution framework provides configurable property testing with parallel processing, custom reporting, seed control, and comprehensive result analysis. It supports both individual property testing and batch execution of property collections.

Capabilities

Test Parameters

Comprehensive configuration for test execution behavior and resource management.

sealed abstract class Test.Parameters {
  val minSuccessfulTests: Int
  val minSize: Int  
  val maxSize: Int
  val workers: Int
  val testCallback: Test.TestCallback
  val maxDiscardRatio: Float
  val customClassLoader: Option[ClassLoader]
  val propFilter: Option[String]
  val initialSeed: Option[Seed]
  val useLegacyShrinking: Boolean
  val maxRNGSpins: Int
  
  def withMinSuccessfulTests(minSuccessfulTests: Int): Test.Parameters
  def withMinSize(minSize: Int): Test.Parameters
  def withMaxSize(maxSize: Int): Test.Parameters
  def withWorkers(workers: Int): Test.Parameters
  def withTestCallback(testCallback: Test.TestCallback): Test.Parameters
  def withMaxDiscardRatio(maxDiscardRatio: Float): Test.Parameters
  def withCustomClassLoader(customClassLoader: Option[ClassLoader]): Test.Parameters
  def withPropFilter(propFilter: Option[String]): Test.Parameters
  def withInitialSeed(seed: Seed): Test.Parameters
  def withLegacyShrinking(b: Boolean): Test.Parameters
  def withMaxRNGSpins(n: Int): Test.Parameters
}

object Test.Parameters {
  val default: Test.Parameters
  val defaultVerbose: Test.Parameters
}

Usage Examples:

val customParams = Test.Parameters.default
  .withMinSuccessfulTests(1000)
  .withWorkers(4)
  .withMaxSize(50)
  .withMaxDiscardRatio(10.0f)

val debugParams = Test.Parameters.default
  .withInitialSeed(Seed.fromBase64("abc123...").get)
  .withTestCallback(ConsoleReporter(2))

Test Execution Methods

Core methods for running individual properties and property collections.

object Test {
  def check(params: Test.Parameters, p: Prop): Test.Result
  def check(p: Prop)(f: Test.Parameters => Test.Parameters): Test.Result
  def check_(params: Test.Parameters, p: Prop): Unit
  def check_(p: Prop)(f: Test.Parameters => Test.Parameters): Unit
  
  def checkProperties(prms: Test.Parameters, ps: Properties): Seq[(String, Test.Result)]
  def checkProperties_(prms: Test.Parameters, ps: Properties): Unit
}

Usage Examples:

val prop = forAll { (x: Int) => x + 0 == x }

// Basic checking
val result = Test.check(Test.Parameters.default, prop)

// Functional parameter modification
val result2 = Test.check(prop)(_.withMinSuccessfulTests(500))

// Silent checking (no return value)
Test.check_(prop)(_.withWorkers(2))

// Batch property checking
object MyProps extends Properties("Math") {
  property("addition") = forAll((a: Int, b: Int) => a + b == b + a)
  property("multiplication") = forAll((a: Int, b: Int) => a * b == b * a)
}

val allResults = Test.checkProperties(Test.Parameters.default, MyProps)

Test Results

Comprehensive result information including status, statistics, and collected data.

case class Test.Result(
  status: Test.Status,
  succeeded: Int,
  discarded: Int,
  freqMap: FreqMap[Set[Any]],
  time: Long
) {
  def passed: Boolean
}

sealed trait Test.Status
case object Test.Passed extends Test.Status
case class Test.Proved(args: List[Prop.Arg[Any]]) extends Test.Status
case class Test.Failed(args: List[Prop.Arg[Any]], labels: Set[String]) extends Test.Status
case object Test.Exhausted extends Test.Status  
case class Test.PropException(args: List[Prop.Arg[Any]], e: Throwable, labels: Set[String]) extends Test.Status

Usage Examples:

val result = Test.check(prop)(_.withMinSuccessfulTests(100))

result.status match {
  case Test.Passed => println(s"✓ Property passed with ${result.succeeded} successful tests")
  case Test.Failed(args, labels) => 
    println(s"✗ Property failed with args: ${args.map(_.arg)}")
    println(s"Labels: ${labels.mkString(", ")}")
  case Test.Exhausted => 
    println(s"⚠ Property exhausted after ${result.discarded} discarded tests")
  case Test.PropException(args, e, labels) =>
    println(s"💥 Property threw exception: ${e.getMessage}")
  case Test.Proved(args) =>
    println(s"✓ Property proved with args: ${args.map(_.arg)}")
}

println(s"Execution time: ${result.time}ms")
println(s"Success rate: ${result.succeeded}/${result.succeeded + result.discarded}")

Test Callbacks

Customizable reporting and monitoring during test execution.

trait Test.TestCallback {
  def onPropEval(name: String, threadIdx: Int, succeeded: Int, discarded: Int): Unit
  def onTestResult(name: String, result: Test.Result): Unit  
  def chain(testCallback: Test.TestCallback): Test.TestCallback
}

class ConsoleReporter(verbosity: Int, columnWidth: Int = 75) extends Test.TestCallback
object ConsoleReporter {
  def apply(verbosity: Int = 0): ConsoleReporter
}

Usage Examples:

// Custom callback implementation
class ProgressCallback extends Test.TestCallback {
  def onPropEval(name: String, threadIdx: Int, succeeded: Int, discarded: Int): Unit = {
    if (succeeded % 10 == 0) print(".")
  }
  
  def onTestResult(name: String, result: Test.Result): Unit = {
    println(s"\n$name: ${if (result.passed) "PASS" else "FAIL"}")
  }
}

// Using console reporter with different verbosity levels
val quietReporter = ConsoleReporter(0)  // Minimal output
val verboseReporter = ConsoleReporter(2) // Detailed output
val customReporter = ConsoleReporter(1).chain(new ProgressCallback)

Test.check(prop)(_.withTestCallback(customReporter))

Property Filtering

Selective execution of properties based on name patterns.

def matchPropFilter(propertyName: String, regex: Regex): Boolean

Usage Examples:

val params = Test.Parameters.default.withPropFilter(Some(".*math.*"))

// Only properties with "math" in their name will be executed
Test.checkProperties_(params, AllProperties)

// In a Properties collection
object MathProperties extends Properties("Math") {
  property("math.addition") = forAll((a: Int, b: Int) => a + b == b + a)
  property("math.multiplication") = forAll((a: Int, b: Int) => a * b == b * a) 
  property("string.concat") = forAll((s1: String, s2: String) => (s1 + s2).length >= s1.length)
}

// With filter "math.*", only the first two properties will run

Parallel Execution

Multi-threaded test execution for improved performance.

// Configure worker threads
val parallelParams = Test.Parameters.default.withWorkers(8)

// Thread-safe property testing
val heavyProp = forAll(complexDataGen) { data =>
  // CPU-intensive property test
  expensiveComputation(data)
}

Test.check(heavyProp)(_.withWorkers(4).withMinSuccessfulTests(10000))

Seed Control

Deterministic test execution using explicit seeds for reproducibility.

// Create deterministic seed
val seed = Seed.fromBase64("SGVsbG8gV29ybGQhIFRoaXMgaXMgYSB0ZXN0Lg").get

// Use seed for reproducible testing
val reproducibleParams = Test.Parameters.default.withInitialSeed(seed)

Test.check(prop)(_.withInitialSeed(seed))

// Get failing seed from property
val failingProp = Prop.forAll { (x: Int) => x > 0 }.viewSeed("myProperty")
// This will print the seed if the property fails

Performance Tuning

Configuration options for optimizing test execution performance.

val performanceParams = Test.Parameters.default
  .withMinSuccessfulTests(10000)    // More thorough testing
  .withWorkers(Runtime.getRuntime.availableProcessors()) // Use all CPU cores
  .withMaxSize(100)                 // Larger test cases
  .withMaxDiscardRatio(50.0f)       // Allow more discards
  .withLegacyShrinking(false)       // Use modern shrinking
  .withMaxRNGSpins(1000000)         // More RNG attempts

// For quick smoke tests
val quickParams = Test.Parameters.default
  .withMinSuccessfulTests(50)
  .withMaxSize(20)
  .withWorkers(1)

Integration Patterns

Property Suites

object ApplicationTests extends Properties("Application") {
  include(CoreLogicTests)
  include(DatabaseTests, "db.")
  include(ApiTests, "api.")
  
  override def overrideParameters(p: Test.Parameters): Test.Parameters = {
    p.withMinSuccessfulTests(500)
     .withWorkers(2)
  }
}

// Run all tests
ApplicationTests.check()

// Command line execution
ApplicationTests.main(Array("--verbosity", "2", "--workers", "4"))

Custom Result Handling

def analyzeResults(results: Seq[(String, Test.Result)]): Unit = {
  val (passed, failed) = results.partition(_._2.passed)
  
  println(s"Summary: ${passed.size} passed, ${failed.size} failed")
  
  failed.foreach { case (name, result) =>
    println(s"FAILED: $name")
    result.status match {
      case Test.Failed(args, labels) => 
        println(s"  Args: ${args.map(_.arg).mkString(", ")}")
        println(s"  Labels: ${labels.mkString(", ")}")
      case Test.PropException(_, e, _) =>
        println(s"  Exception: ${e.getMessage}")
      case _ =>
    }
  }
}

val results = Test.checkProperties(Test.Parameters.default, MyProperties)
analyzeResults(results)

CI/CD Integration

// Exit with proper codes for CI systems
object CITestRunner {
  def main(args: Array[String]): Unit = {
    val results = Test.checkProperties(
      Test.Parameters.default.withTestCallback(ConsoleReporter(1)), 
      AllTests
    )
    
    val failures = results.count(!_._2.passed)
    if (failures > 0) {
      println(s"BUILD FAILED: $failures test(s) failed")
      System.exit(1)
    } else {
      println("BUILD PASSED: All tests successful")
      System.exit(0)
    }
  }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-scalacheck--scalacheck-2-12

docs

arbitrary.md

cogen.md

generators.md

index.md

properties.md

property-collections.md

shrinking.md

stateful-testing.md

test-execution.md

tile.json