0
# Test Execution and Configuration
1
2
Specs2 provides comprehensive test execution capabilities with flexible configuration options, multiple runners for different environments, and detailed control over test execution behavior.
3
4
## Core Execution
5
6
### Runner
7
8
Main execution utility for running specifications.
9
10
```scala { .api }
11
object Runner {
12
def execute(actions: Action[Unit], arguments: Arguments, exit: Boolean): Unit
13
def execute(specs: Seq[SpecificationStructure], arguments: Arguments, exit: Boolean): Unit
14
def run(specs: SpecificationStructure*): Unit
15
}
16
```
17
18
### Executor
19
20
Core execution engine that processes specification fragments using stream-based processing.
21
22
```scala { .api }
23
trait Executor {
24
def execute(env: Env): Process[Task, Fragment] => Process[Task, Fragment]
25
def execute1(env: Env): Process1[Fragment, Task[Fragment]]
26
}
27
```
28
29
The executor is responsible for:
30
- Converting fragments into executable tasks
31
- Managing parallel vs sequential execution
32
- Handling fragment dependencies and ordering
33
- Coordinating step and action execution
34
35
### DefaultExecutor
36
37
Default implementation of the Executor trait using scalaz-stream processing.
38
39
```scala { .api }
40
trait DefaultExecutor extends Executor {
41
def execute1(env: Env): Process1[Fragment, Task[Fragment]]
42
def sequencedExecution(env: Env): Process1[Fragment, Task[Fragment]]
43
def isolatedExecution(env: Env): Process1[Fragment, Task[Fragment]]
44
}
45
```
46
47
**Execution Strategies:**
48
- **Sequenced**: Examples run one after another
49
- **Isolated**: Each example runs in complete isolation
50
- **Parallel**: Examples run concurrently (default)
51
52
### Env (Environment)
53
54
Execution environment that holds configuration and resources for test execution.
55
56
```scala { .api }
57
case class Env(
58
arguments: Arguments,
59
systemLogger: Logger,
60
printers: List[Printer] = Nil,
61
statisticsRepository: StatisticsRepository = StatisticsRepository.memory,
62
random: scala.util.Random = new scala.util.Random,
63
fileSystem: FileSystem = FileSystem,
64
executionContext: ExecutionContext = ExecutionContext.global
65
) {
66
def setArguments(args: Arguments): Env
67
def setPrinters(ps: List[Printer]): Env
68
def addPrinter(p: Printer): Env
69
}
70
```
71
72
The environment provides:
73
- Execution arguments and configuration
74
- Logging infrastructure
75
- Output printers for reporting
76
- Statistics collection
77
- File system access
78
- Execution context for concurrent operations
79
80
## Fragment Execution Lifecycle
81
82
### Process-Based Execution Model
83
84
Specs2 uses scalaz-stream `Process[Task, Fragment]` for fragment processing, enabling:
85
86
- **Lazy evaluation**: Fragments are processed on-demand
87
- **Stream composition**: Fragment streams can be combined and transformed
88
- **Resource management**: Automatic cleanup of resources
89
- **Backpressure handling**: Controlled memory usage for large test suites
90
91
```scala { .api }
92
// Core execution pipeline
93
trait SpecificationExecution {
94
def executeFragments(env: Env): Process[Task, Fragment] => Process[Task, Fragment]
95
def executeBodies(env: Env): Process1[Fragment, Fragment]
96
def executeActions(env: Env): Process1[Fragment, Fragment]
97
}
98
```
99
100
### Fragment Processing Pipeline
101
102
1. **Fragment Creation**: Specification `is` method creates fragment stream
103
2. **Body Execution**: Example bodies are executed to produce results
104
3. **Action Processing**: Steps and actions are executed at appropriate times
105
4. **Result Collection**: Results are collected for reporting
106
5. **Statistics Gathering**: Execution statistics are accumulated
107
108
### Synchronization and Ordering
109
110
```scala { .api }
111
trait SpecificationStructure {
112
def fragments: Process[Task, Fragment]
113
def linked: Process[Task, Fragment]
114
def contents: Process[Task, Fragment]
115
}
116
```
117
118
**Fragment Ordering:**
119
- **Steps**: Executed immediately during fragment stream processing
120
- **Examples**: Executed according to execution strategy (parallel/sequential)
121
- **Actions**: Executed after example completion
122
- **Text/Formatting**: Processed for output formatting
123
124
**Usage Example:**
125
```scala
126
// Run a single specification
127
Runner.run(new MySpec)
128
129
// Run multiple specifications
130
Runner.run(new UserSpec, new OrderSpec, new PaymentSpec)
131
132
// Run with custom arguments
133
Runner.execute(
134
List(new IntegrationSpec),
135
Arguments(sequential = true, stopOnFail = true),
136
exit = false
137
)
138
```
139
140
## Test Runners
141
142
### ClassRunner
143
144
Runs specifications from fully qualified class names.
145
146
```scala { .api }
147
class ClassRunner {
148
def run(className: String): Unit
149
def run(className: String, arguments: Arguments): Unit
150
def run(classNames: List[String], arguments: Arguments): Unit
151
}
152
```
153
154
**Usage:**
155
```bash
156
# Command line execution
157
scala -cp "classpath" org.specs2.runner.ClassRunner com.example.UserSpec
158
159
# With arguments
160
scala -cp "classpath" org.specs2.runner.ClassRunner com.example.UserSpec -- sequential
161
```
162
163
### FilesRunner
164
165
Discovers and runs specification files from filesystem.
166
167
```scala { .api }
168
class FilesRunner {
169
def run(path: String): Unit
170
def run(path: String, pattern: String): Unit
171
def run(paths: List[String], arguments: Arguments): Unit
172
}
173
```
174
175
**Usage:**
176
```bash
177
# Run all specs in directory
178
scala -cp "classpath" org.specs2.runner.FilesRunner src/test/scala
179
180
# Run specs matching pattern
181
scala -cp "classpath" org.specs2.runner.FilesRunner src/test/scala ".*UserSpec.*"
182
```
183
184
### SbtRunner
185
186
Integration with SBT test framework.
187
188
```scala { .api }
189
class SbtRunner extends TestFramework {
190
def name: String = "specs2"
191
def fingerprints: Array[Fingerprint]
192
def runner(args: Array[String], remoteArgs: Array[String], testClassLoader: ClassLoader): Runner2
193
}
194
```
195
196
**SBT Configuration:**
197
```scala
198
// build.sbt
199
libraryDependencies += "org.specs2" %% "specs2-core" % "3.3.1" % "test"
200
testFrameworks += TestFrameworks.Specs2
201
202
// Run all tests
203
sbt test
204
205
// Run specific test
206
sbt "testOnly com.example.UserSpec"
207
208
// Run with arguments
209
sbt "testOnly * -- sequential stopOnFail"
210
```
211
212
### NotifierRunner
213
214
Integration with test framework notifiers for IDE support.
215
216
```scala { .api }
217
class NotifierRunner {
218
def run(specs: List[SpecificationStructure], notifier: EventHandler): Unit
219
def run(className: String, notifier: EventHandler): Unit
220
}
221
```
222
223
## Configuration System
224
225
### Arguments
226
227
Main configuration object controlling test execution behavior.
228
229
```scala { .api }
230
case class Arguments(
231
// Execution control
232
plan: Boolean = false,
233
skipAll: Boolean = false,
234
stopOnFail: Boolean = false,
235
sequential: Boolean = false,
236
isolated: Boolean = false,
237
threadsNb: Int = Runtime.getRuntime.availableProcessors,
238
239
// Filtering
240
include: String = "",
241
exclude: String = "",
242
243
// Output control
244
colors: Boolean = true,
245
noindent: Boolean = false,
246
showTimes: Boolean = false,
247
offset: Int = 0,
248
249
// Reporting
250
console: Boolean = true,
251
html: Boolean = false,
252
markdown: Boolean = false,
253
junitxml: Boolean = false,
254
255
// File paths
256
outdir: String = "target/specs2-reports",
257
srcdir: String = "src/test/scala"
258
)
259
```
260
261
### ArgumentsArgs
262
263
Command-line argument parsing for Arguments object.
264
265
```scala { .api }
266
trait ArgumentsArgs {
267
def parse(args: Array[String]): Arguments
268
def parseArguments(args: String*): Arguments
269
}
270
```
271
272
**Command Line Usage:**
273
```bash
274
# Basic arguments
275
--sequential # Run examples sequentially
276
--stopOnFail # Stop on first failure
277
--plan # Show execution plan only
278
--skipAll # Skip all examples
279
280
# Filtering
281
--include "unit" # Include examples tagged with "unit"
282
--exclude "slow" # Exclude examples tagged with "slow"
283
284
# Output control
285
--colors # Enable colors (default)
286
--noColors # Disable colors
287
--showTimes # Show execution times
288
--offset 2 # Indent output by 2 spaces
289
290
# Reporting formats
291
--console # Console output (default)
292
--html # Generate HTML reports
293
--markdown # Generate Markdown reports
294
--junitxml # Generate JUnit XML reports
295
296
# File paths
297
--outdir target/reports # Output directory
298
--srcdir src/test/scala # Source directory
299
```
300
301
### ArgumentsShortcuts
302
303
Convenient methods for creating common argument combinations.
304
305
```scala { .api }
306
trait ArgumentsShortcuts {
307
def sequential: Arguments
308
def isolated: Arguments
309
def stopOnFail: Arguments
310
def plan: Arguments
311
def skipAll: Arguments
312
def noColors: Arguments
313
def showTimes: Arguments
314
def html: Arguments
315
def markdown: Arguments
316
def junitxml: Arguments
317
}
318
```
319
320
**Usage in Specifications:**
321
```scala
322
class ConfiguredSpec extends Specification { def is =
323
args(sequential, stopOnFail, showTimes) ^ s2"""
324
Configured specification
325
test 1 $test1
326
test 2 $test2
327
test 3 $test3
328
"""
329
}
330
```
331
332
## Execution Control
333
334
### Execute
335
336
Execution lifecycle control and coordination.
337
338
```scala { .api }
339
trait Execute {
340
def execute[T](action: Action[T]): T
341
def execute[T](action: Action[T], timeout: FiniteDuration): T
342
def executeAll[T](actions: List[Action[T]]): List[T]
343
def executeSequentially[T](actions: List[Action[T]]): List[T]
344
def executeConcurrently[T](actions: List[Action[T]]): List[T]
345
}
346
```
347
348
### Action[T]
349
350
Monadic action type for composable operations with error handling.
351
352
```scala { .api }
353
case class Action[T](run: () => T) {
354
def map[S](f: T => S): Action[S]
355
def flatMap[S](f: T => Action[S]): Action[S]
356
def filter(p: T => Boolean): Action[T]
357
def recover(f: Throwable => T): Action[T]
358
def timeout(duration: FiniteDuration): Action[T]
359
}
360
```
361
362
**Usage Example:**
363
```scala
364
val setupAction = Action { () =>
365
Database.createTables()
366
Database.seedTestData()
367
}
368
369
val testAction = Action { () =>
370
Database.query("SELECT * FROM users") must not(beEmpty)
371
}
372
373
val cleanupAction = Action { () =>
374
Database.cleanup()
375
}
376
377
val composedAction = for {
378
_ <- setupAction
379
result <- testAction
380
_ <- cleanupAction
381
} yield result
382
```
383
384
## Specification Discovery
385
386
### SpecificationsFinder
387
388
Discovers specification classes dynamically.
389
390
```scala { .api }
391
trait SpecificationsFinder {
392
def find(pattern: String): List[String]
393
def find(classLoader: ClassLoader, pattern: String): List[String]
394
def findSpecifications(packages: List[String]): List[SpecificationStructure]
395
}
396
```
397
398
**Usage:**
399
```scala
400
val finder = new SpecificationsFinder {}
401
val specClasses = finder.find("com.example.*Spec")
402
val specifications = finder.findSpecifications(List("com.example"))
403
```
404
405
### Specification Path Discovery
406
407
Automatic discovery patterns:
408
409
```scala
410
// File-based discovery
411
val fileSpecs = FilesRunner.findSpecifications("src/test/scala")
412
413
// Package-based discovery
414
val packageSpecs = ClassRunner.findSpecifications("com.example")
415
416
// Pattern-based discovery
417
val patternSpecs = SpecificationsFinder.find(".*IntegrationSpec.*")
418
```
419
420
## Execution Modes
421
422
### Sequential Execution
423
424
Run examples one after another:
425
426
```scala
427
class SequentialSpec extends Specification { def is = sequential ^ s2"""
428
Sequential execution (examples run in order)
429
setup step $setup
430
test operation $testOp
431
verify result $verify
432
cleanup step $cleanup
433
"""
434
}
435
```
436
437
### Parallel Execution
438
439
Run examples concurrently (default):
440
441
```scala
442
class ParallelSpec extends Specification { def is = s2"""
443
Parallel execution (examples run concurrently)
444
independent test 1 $test1
445
independent test 2 $test2
446
independent test 3 $test3
447
"""
448
}
449
```
450
451
### Isolated Execution
452
453
Run each example in isolation:
454
455
```scala
456
class IsolatedSpec extends Specification { def is = isolated ^ s2"""
457
Isolated execution (examples in separate classloaders)
458
test with global state 1 $testGlobal1
459
test with global state 2 $testGlobal2
460
"""
461
}
462
```
463
464
## Filtering and Selection
465
466
### Tag-Based Filtering
467
468
Filter examples by tags:
469
470
```bash
471
# Include specific tags
472
sbt "testOnly * -- include unit,fast"
473
474
# Exclude specific tags
475
sbt "testOnly * -- exclude slow,integration"
476
477
# Complex filtering
478
sbt "testOnly * -- include unit exclude broken"
479
```
480
481
### Pattern-Based Filtering
482
483
Filter by specification or example names:
484
485
```bash
486
# Run specifications matching pattern
487
sbt "testOnly *UserSpec*"
488
489
# Run examples matching description
490
sbt "testOnly * -- ex create.*user"
491
```
492
493
### Conditional Execution
494
495
Skip examples based on conditions:
496
497
```scala
498
class ConditionalSpec extends Specification { def is = s2"""
499
Conditional execution
500
${if (System.getProperty("integration") == "true")
501
"integration test" ! integrationTest
502
else
503
"integration test (skipped)" ! skipped
504
}
505
unit test $unitTest
506
"""
507
}
508
```
509
510
## Error Handling and Recovery
511
512
### StopOnFail
513
514
Stop execution on first failure:
515
516
```scala
517
class StopOnFailSpec extends Specification { def is =
518
args(stopOnFail = true) ^ s2"""
519
Stop on fail behavior
520
test 1 (will pass) $test1
521
test 2 (will fail) $test2
522
test 3 (won't run) $test3
523
"""
524
```
525
526
### Exception Handling
527
528
Handle exceptions during execution:
529
530
```scala
531
class ExceptionHandlingSpec extends Specification { def is = s2"""
532
Exception handling
533
recoverable error $recoverableError
534
fatal error $fatalError
535
"""
536
537
def recoverableError = {
538
try {
539
riskyOperation()
540
success
541
} catch {
542
case _: RecoverableException =>
543
fallbackOperation() must beEqualTo(expected)
544
}
545
}
546
547
def fatalError = {
548
fatalOperation() must throwA[FatalException]
549
}
550
}
551
```
552
553
## Performance and Monitoring
554
555
### Execution Timing
556
557
Track execution performance:
558
559
```bash
560
# Show execution times
561
sbt "testOnly * -- showTimes"
562
563
# Show times with colors
564
sbt "testOnly * -- showTimes colors"
565
```
566
567
### Thread Configuration
568
569
Control concurrent execution:
570
571
```scala
572
// Limit concurrent threads
573
Arguments(threadsNb = 4)
574
575
// Use all available processors (default)
576
Arguments(threadsNb = Runtime.getRuntime.availableProcessors)
577
```
578
579
### Memory Management
580
581
Control memory usage during execution:
582
583
```scala
584
// Run with isolated classloaders (higher memory)
585
Arguments(isolated = true)
586
587
// Run sequentially (lower memory)
588
Arguments(sequential = true)
589
```
590
591
## Integration Patterns
592
593
### Continuous Integration
594
595
CI-friendly configuration:
596
597
```scala
598
class CISpec extends Specification { def is =
599
args(
600
stopOnFail = true, // Fail fast
601
noColors = true, // No ANSI colors
602
junitxml = true, // Generate XML reports
603
html = false // Skip HTML for CI
604
) ^ s2"""
605
CI-optimized specification
606
critical test 1 $test1
607
critical test 2 $test2
608
"""
609
```
610
611
### IDE Integration
612
613
IDE-friendly execution:
614
615
```scala
616
// IntelliJ IDEA runner support
617
@RunWith(classOf[JUnitRunner])
618
class IDESpec extends Specification { def is = s2"""
619
IDE-compatible specification
620
test 1 $test1
621
test 2 $test2
622
"""
623
}
624
```
625
626
### Build Tool Integration
627
628
Maven integration:
629
630
```xml
631
<plugin>
632
<groupId>org.scalatest</groupId>
633
<artifactId>scalatest-maven-plugin</artifactId>
634
<configuration>
635
<reportsDirectory>${project.build.directory}/surefire-reports</reportsDirectory>
636
<junitxml>.</junitxml>
637
<filereports>WDF TestSuite.txt</filereports>
638
</configuration>
639
</plugin>
640
```
641
642
## Best Practices
643
644
1. **Use appropriate execution mode**: Sequential for dependent tests, parallel for independent tests
645
2. **Configure for environment**: Different arguments for development vs CI
646
3. **Filter strategically**: Use tags and patterns for selective test execution
647
4. **Handle failures gracefully**: Use `stopOnFail` judiciously and handle exceptions properly
648
5. **Monitor performance**: Use timing information to identify slow tests
649
6. **Optimize resource usage**: Balance parallelism with available resources
650
7. **Integrate with tools**: Configure for CI/CD and IDE support
651
8. **Document execution requirements**: Clearly specify any special execution needs