0
# Test Execution
1
2
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.
3
4
## Capabilities
5
6
### Test Parameters
7
8
Comprehensive configuration for test execution behavior and resource management.
9
10
```scala { .api }
11
sealed abstract class Test.Parameters {
12
val minSuccessfulTests: Int
13
val minSize: Int
14
val maxSize: Int
15
val workers: Int
16
val testCallback: Test.TestCallback
17
val maxDiscardRatio: Float
18
val customClassLoader: Option[ClassLoader]
19
val propFilter: Option[String]
20
val initialSeed: Option[Seed]
21
val useLegacyShrinking: Boolean
22
val maxRNGSpins: Int
23
24
def withMinSuccessfulTests(minSuccessfulTests: Int): Test.Parameters
25
def withMinSize(minSize: Int): Test.Parameters
26
def withMaxSize(maxSize: Int): Test.Parameters
27
def withWorkers(workers: Int): Test.Parameters
28
def withTestCallback(testCallback: Test.TestCallback): Test.Parameters
29
def withMaxDiscardRatio(maxDiscardRatio: Float): Test.Parameters
30
def withCustomClassLoader(customClassLoader: Option[ClassLoader]): Test.Parameters
31
def withPropFilter(propFilter: Option[String]): Test.Parameters
32
def withInitialSeed(seed: Seed): Test.Parameters
33
def withLegacyShrinking(b: Boolean): Test.Parameters
34
def withMaxRNGSpins(n: Int): Test.Parameters
35
}
36
37
object Test.Parameters {
38
val default: Test.Parameters
39
val defaultVerbose: Test.Parameters
40
}
41
```
42
43
**Usage Examples:**
44
```scala
45
val customParams = Test.Parameters.default
46
.withMinSuccessfulTests(1000)
47
.withWorkers(4)
48
.withMaxSize(50)
49
.withMaxDiscardRatio(10.0f)
50
51
val debugParams = Test.Parameters.default
52
.withInitialSeed(Seed.fromBase64("abc123...").get)
53
.withTestCallback(ConsoleReporter(2))
54
```
55
56
### Test Execution Methods
57
58
Core methods for running individual properties and property collections.
59
60
```scala { .api }
61
object Test {
62
def check(params: Test.Parameters, p: Prop): Test.Result
63
def check(p: Prop)(f: Test.Parameters => Test.Parameters): Test.Result
64
def check_(params: Test.Parameters, p: Prop): Unit
65
def check_(p: Prop)(f: Test.Parameters => Test.Parameters): Unit
66
67
def checkProperties(prms: Test.Parameters, ps: Properties): Seq[(String, Test.Result)]
68
def checkProperties_(prms: Test.Parameters, ps: Properties): Unit
69
}
70
```
71
72
**Usage Examples:**
73
```scala
74
val prop = forAll { (x: Int) => x + 0 == x }
75
76
// Basic checking
77
val result = Test.check(Test.Parameters.default, prop)
78
79
// Functional parameter modification
80
val result2 = Test.check(prop)(_.withMinSuccessfulTests(500))
81
82
// Silent checking (no return value)
83
Test.check_(prop)(_.withWorkers(2))
84
85
// Batch property checking
86
object MyProps extends Properties("Math") {
87
property("addition") = forAll((a: Int, b: Int) => a + b == b + a)
88
property("multiplication") = forAll((a: Int, b: Int) => a * b == b * a)
89
}
90
91
val allResults = Test.checkProperties(Test.Parameters.default, MyProps)
92
```
93
94
### Test Results
95
96
Comprehensive result information including status, statistics, and collected data.
97
98
```scala { .api }
99
case class Test.Result(
100
status: Test.Status,
101
succeeded: Int,
102
discarded: Int,
103
freqMap: FreqMap[Set[Any]],
104
time: Long
105
) {
106
def passed: Boolean
107
}
108
109
sealed trait Test.Status
110
case object Test.Passed extends Test.Status
111
case class Test.Proved(args: List[Prop.Arg[Any]]) extends Test.Status
112
case class Test.Failed(args: List[Prop.Arg[Any]], labels: Set[String]) extends Test.Status
113
case object Test.Exhausted extends Test.Status
114
case class Test.PropException(args: List[Prop.Arg[Any]], e: Throwable, labels: Set[String]) extends Test.Status
115
```
116
117
**Usage Examples:**
118
```scala
119
val result = Test.check(prop)(_.withMinSuccessfulTests(100))
120
121
result.status match {
122
case Test.Passed => println(s"β Property passed with ${result.succeeded} successful tests")
123
case Test.Failed(args, labels) =>
124
println(s"β Property failed with args: ${args.map(_.arg)}")
125
println(s"Labels: ${labels.mkString(", ")}")
126
case Test.Exhausted =>
127
println(s"β Property exhausted after ${result.discarded} discarded tests")
128
case Test.PropException(args, e, labels) =>
129
println(s"π₯ Property threw exception: ${e.getMessage}")
130
case Test.Proved(args) =>
131
println(s"β Property proved with args: ${args.map(_.arg)}")
132
}
133
134
println(s"Execution time: ${result.time}ms")
135
println(s"Success rate: ${result.succeeded}/${result.succeeded + result.discarded}")
136
```
137
138
### Test Callbacks
139
140
Customizable reporting and monitoring during test execution.
141
142
```scala { .api }
143
trait Test.TestCallback {
144
def onPropEval(name: String, threadIdx: Int, succeeded: Int, discarded: Int): Unit
145
def onTestResult(name: String, result: Test.Result): Unit
146
def chain(testCallback: Test.TestCallback): Test.TestCallback
147
}
148
149
class ConsoleReporter(verbosity: Int, columnWidth: Int = 75) extends Test.TestCallback
150
object ConsoleReporter {
151
def apply(verbosity: Int = 0): ConsoleReporter
152
}
153
```
154
155
**Usage Examples:**
156
```scala
157
// Custom callback implementation
158
class ProgressCallback extends Test.TestCallback {
159
def onPropEval(name: String, threadIdx: Int, succeeded: Int, discarded: Int): Unit = {
160
if (succeeded % 10 == 0) print(".")
161
}
162
163
def onTestResult(name: String, result: Test.Result): Unit = {
164
println(s"\n$name: ${if (result.passed) "PASS" else "FAIL"}")
165
}
166
}
167
168
// Using console reporter with different verbosity levels
169
val quietReporter = ConsoleReporter(0) // Minimal output
170
val verboseReporter = ConsoleReporter(2) // Detailed output
171
val customReporter = ConsoleReporter(1).chain(new ProgressCallback)
172
173
Test.check(prop)(_.withTestCallback(customReporter))
174
```
175
176
### Property Filtering
177
178
Selective execution of properties based on name patterns.
179
180
```scala { .api }
181
def matchPropFilter(propertyName: String, regex: Regex): Boolean
182
```
183
184
**Usage Examples:**
185
```scala
186
val params = Test.Parameters.default.withPropFilter(Some(".*math.*"))
187
188
// Only properties with "math" in their name will be executed
189
Test.checkProperties_(params, AllProperties)
190
191
// In a Properties collection
192
object MathProperties extends Properties("Math") {
193
property("math.addition") = forAll((a: Int, b: Int) => a + b == b + a)
194
property("math.multiplication") = forAll((a: Int, b: Int) => a * b == b * a)
195
property("string.concat") = forAll((s1: String, s2: String) => (s1 + s2).length >= s1.length)
196
}
197
198
// With filter "math.*", only the first two properties will run
199
```
200
201
### Parallel Execution
202
203
Multi-threaded test execution for improved performance.
204
205
```scala { .api }
206
// Configure worker threads
207
val parallelParams = Test.Parameters.default.withWorkers(8)
208
209
// Thread-safe property testing
210
val heavyProp = forAll(complexDataGen) { data =>
211
// CPU-intensive property test
212
expensiveComputation(data)
213
}
214
215
Test.check(heavyProp)(_.withWorkers(4).withMinSuccessfulTests(10000))
216
```
217
218
### Seed Control
219
220
Deterministic test execution using explicit seeds for reproducibility.
221
222
```scala { .api }
223
// Create deterministic seed
224
val seed = Seed.fromBase64("SGVsbG8gV29ybGQhIFRoaXMgaXMgYSB0ZXN0Lg").get
225
226
// Use seed for reproducible testing
227
val reproducibleParams = Test.Parameters.default.withInitialSeed(seed)
228
229
Test.check(prop)(_.withInitialSeed(seed))
230
231
// Get failing seed from property
232
val failingProp = Prop.forAll { (x: Int) => x > 0 }.viewSeed("myProperty")
233
// This will print the seed if the property fails
234
```
235
236
### Performance Tuning
237
238
Configuration options for optimizing test execution performance.
239
240
```scala { .api }
241
val performanceParams = Test.Parameters.default
242
.withMinSuccessfulTests(10000) // More thorough testing
243
.withWorkers(Runtime.getRuntime.availableProcessors()) // Use all CPU cores
244
.withMaxSize(100) // Larger test cases
245
.withMaxDiscardRatio(50.0f) // Allow more discards
246
.withLegacyShrinking(false) // Use modern shrinking
247
.withMaxRNGSpins(1000000) // More RNG attempts
248
249
// For quick smoke tests
250
val quickParams = Test.Parameters.default
251
.withMinSuccessfulTests(50)
252
.withMaxSize(20)
253
.withWorkers(1)
254
```
255
256
## Integration Patterns
257
258
### Property Suites
259
260
```scala
261
object ApplicationTests extends Properties("Application") {
262
include(CoreLogicTests)
263
include(DatabaseTests, "db.")
264
include(ApiTests, "api.")
265
266
override def overrideParameters(p: Test.Parameters): Test.Parameters = {
267
p.withMinSuccessfulTests(500)
268
.withWorkers(2)
269
}
270
}
271
272
// Run all tests
273
ApplicationTests.check()
274
275
// Command line execution
276
ApplicationTests.main(Array("--verbosity", "2", "--workers", "4"))
277
```
278
279
### Custom Result Handling
280
281
```scala
282
def analyzeResults(results: Seq[(String, Test.Result)]): Unit = {
283
val (passed, failed) = results.partition(_._2.passed)
284
285
println(s"Summary: ${passed.size} passed, ${failed.size} failed")
286
287
failed.foreach { case (name, result) =>
288
println(s"FAILED: $name")
289
result.status match {
290
case Test.Failed(args, labels) =>
291
println(s" Args: ${args.map(_.arg).mkString(", ")}")
292
println(s" Labels: ${labels.mkString(", ")}")
293
case Test.PropException(_, e, _) =>
294
println(s" Exception: ${e.getMessage}")
295
case _ =>
296
}
297
}
298
}
299
300
val results = Test.checkProperties(Test.Parameters.default, MyProperties)
301
analyzeResults(results)
302
```
303
304
### CI/CD Integration
305
306
```scala
307
// Exit with proper codes for CI systems
308
object CITestRunner {
309
def main(args: Array[String]): Unit = {
310
val results = Test.checkProperties(
311
Test.Parameters.default.withTestCallback(ConsoleReporter(1)),
312
AllTests
313
)
314
315
val failures = results.count(!_._2.passed)
316
if (failures > 0) {
317
println(s"BUILD FAILED: $failures test(s) failed")
318
System.exit(1)
319
} else {
320
println("BUILD PASSED: All tests successful")
321
System.exit(0)
322
}
323
}
324
}
325
```