or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-specifications.mddsl-components.mdindex.mdintegration-features.mdmatcher-system.mdmutable-specifications.mdreporting.mdtest-execution.md

dsl-components.mddocs/

0

# DSL Components

1

2

Specs2 provides a rich domain-specific language (DSL) for creating readable and expressive test specifications. The DSL components enable natural language-like test definitions with powerful composition and structuring capabilities.

3

4

## Core DSL Traits

5

6

### AcceptanceDsl

7

8

Full acceptance testing DSL combining all DSL components.

9

10

```scala { .api }

11

trait AcceptanceDsl extends FragmentsDsl

12

with SpecStructureDsl

13

with TitleDsl

14

with ExampleDsl

15

with ReferenceDsl

16

with TagDsl

17

with ActionDsl

18

```

19

20

Provides complete DSL functionality for immutable specifications.

21

22

### AcceptanceDsl1

23

24

Lightweight acceptance DSL with essential components only.

25

26

```scala { .api }

27

trait AcceptanceDsl1 extends FragmentsDsl1

28

with ExampleDsl1

29

with TitleDsl1

30

```

31

32

Minimal subset for basic specifications with reduced imports.

33

34

## Example Creation DSL

35

36

### ExampleDsl

37

38

DSL for creating test examples with various syntax options.

39

40

```scala { .api }

41

trait ExampleDsl {

42

def in[T: AsResult](body: => T): Fragment

43

def >>[T: AsResult](body: => T): Fragment

44

def should[T: AsResult](body: => T): Fragment

45

def can[T: AsResult](body: => T): Fragment

46

def todo: Fragment

47

def done: Fragment

48

}

49

```

50

51

**Usage Examples:**

52

```scala

53

class ExampleDslSpec extends Specification { def is = s2"""

54

Calculator should

55

add two numbers correctly ${ 2 + 3 must beEqualTo(5) }

56

handle division by zero ${ 10 / 0 must throwA[ArithmeticException] }

57

58

Advanced operations

59

calculate square root $sqrt

60

compute factorial $factorial

61

parse expressions $todo

62

"""

63

64

def sqrt = Math.sqrt(16) must beEqualTo(4.0)

65

def factorial = factorial(5) must beEqualTo(120)

66

}

67

```

68

69

### ExampleDsl1

70

71

Minimal example DSL with core methods.

72

73

```scala { .api }

74

trait ExampleDsl1 {

75

def in[T: AsResult](body: => T): Fragment

76

def should[T: AsResult](body: => T): Fragment

77

}

78

```

79

80

## Fragment Management DSL

81

82

### FragmentsDsl

83

84

DSL for building and organizing specification fragments.

85

86

```scala { .api }

87

trait FragmentsDsl {

88

def br: Fragment

89

def p: Fragment

90

def end: Fragment

91

def t: Fragment

92

def t(n: Int): Fragment

93

def bt: Fragment

94

def bt(n: Int): Fragment

95

}

96

```

97

98

**Fragment Types:**

99

- `br`: Line break

100

- `p`: Paragraph break

101

- `end`: End specification processing

102

- `t(n)`: Tab indentation (n levels)

103

- `bt(n)`: Back-tab (reduce indentation)

104

105

**Usage Example:**

106

```scala

107

class FormattedSpec extends Specification { def is = s2"""

108

Main section

109

${br}

110

Subsection with indentation

111

${t}example 1 $e1

112

${t}example 2 $e2

113

${bt}

114

Back to main level

115

example 3 $e3

116

"""

117

118

def e1 = success

119

def e2 = success

120

def e3 = success

121

}

122

```

123

124

### FragmentsDsl1

125

126

Minimal fragment DSL.

127

128

```scala { .api }

129

trait FragmentsDsl1 {

130

def br: Fragment

131

def p: Fragment

132

}

133

```

134

135

## Title and Structure DSL

136

137

### TitleDsl

138

139

DSL for creating specification titles and section headers.

140

141

```scala { .api }

142

trait TitleDsl {

143

def title(t: String): Fragment

144

def section(name: String): Fragment

145

def group(name: String): Fragment

146

}

147

```

148

149

**Usage Example:**

150

```scala

151

class TitledSpec extends Specification { def is =

152

title("User Management System") ^

153

section("User Creation") ^ s2"""

154

Creating users should

155

validate required fields $validateRequired

156

generate unique IDs $generateIds

157

""" ^

158

section("User Authentication") ^ s2"""

159

Authentication should

160

verify passwords $verifyPasswords

161

handle invalid credentials $handleInvalid

162

"""

163

```

164

165

### TitleDsl1

166

167

Minimal title DSL.

168

169

```scala { .api }

170

trait TitleDsl1 {

171

def title(t: String): Fragment

172

}

173

```

174

175

## Specification Structure DSL

176

177

### SpecStructureDsl

178

179

DSL for organizing specification structure and flow control.

180

181

```scala { .api }

182

trait SpecStructureDsl {

183

def sequential: Fragment

184

def isolated: Fragment

185

def stopOnFail: Fragment

186

def skipAll: Fragment

187

def plan: Fragment

188

def args(arguments: Arguments): Fragment

189

}

190

```

191

192

**Usage Example:**

193

```scala

194

class StructuredSpec extends Specification { def is =

195

args(sequential = true, stopOnFail = true) ^ s2"""

196

Integration tests (run sequentially)

197

setup database $setupDb

198

create test data $createData

199

run main tests $runTests

200

cleanup $cleanup

201

"""

202

```

203

204

## Tagging and Categorization DSL

205

206

### TagDsl

207

208

DSL for tagging examples and sections for organization and filtering.

209

210

```scala { .api }

211

trait TagDsl {

212

def tag(names: String*): Fragment

213

def section(name: String): Fragment

214

def group(name: String): Fragment

215

}

216

```

217

218

**Usage Example:**

219

```scala

220

class TaggedSpec extends Specification { def is = s2"""

221

User service tests

222

create user (fast test) $createUser

223

${tag("unit", "fast")}

224

225

bulk import users (slow test) $bulkImport

226

${tag("integration", "slow")}

227

228

load test with 1000 users $loadTest

229

${tag("performance", "slow", "manual")}

230

"""

231

```

232

233

### Filtering by Tags

234

235

Run specific tags:

236

```bash

237

# Run only fast tests

238

testOnly *Spec -- include "fast"

239

240

# Exclude slow tests

241

testOnly *Spec -- exclude "slow"

242

243

# Run unit tests only

244

testOnly *Spec -- include "unit" exclude "integration"

245

```

246

247

## Action and Step DSL

248

249

### ActionDsl

250

251

DSL for setup, teardown, and step actions.

252

253

```scala { .api }

254

trait ActionDsl {

255

def step(action: => Any): Fragment

256

def action(action: => Any): Fragment

257

}

258

```

259

260

**Usage Example:**

261

```scala

262

class ActionSpec extends Specification { def is = s2"""

263

Database operations

264

${step(Database.createTables())}

265

insert records $insertRecords

266

${step(Database.seedTestData())}

267

query records $queryRecords

268

update records $updateRecords

269

${step(Database.cleanup())}

270

"""

271

```

272

273

### Step vs Action

274

275

- **Step**: Executed during specification building phase

276

- **Action**: Executed during example execution phase

277

278

## Reference DSL

279

280

### ReferenceDsl

281

282

DSL for including other specifications and creating references.

283

284

```scala { .api }

285

trait ReferenceDsl {

286

def include(spec: SpecificationStructure): Fragment

287

def link(spec: SpecificationStructure): Fragment

288

def see(spec: SpecificationStructure): Fragment

289

}

290

```

291

292

**Usage Example:**

293

```scala

294

class MainSpec extends Specification { def is = s2"""

295

Complete test suite

296

${include(new UserSpec)}

297

${include(new OrderSpec)}

298

${link(new PerformanceSpec)}

299

"""

300

```

301

302

## String Context DSL

303

304

### S2StringContext

305

306

Advanced string interpolation for specifications.

307

308

```scala { .api }

309

trait S2StringContext {

310

implicit class S2StringContext(sc: StringContext) {

311

def s2(args: Any*): Fragments

312

}

313

}

314

```

315

316

**Usage Patterns:**

317

```scala

318

class InterpolatedSpec extends Specification { def is = s2"""

319

String interpolation examples

320

example with variable ${variable must beEqualTo(expected)}

321

example with method call ${method() must beEqualTo(result)}

322

example with complex expr ${complexCalculation must satisfy(predicate)}

323

"""

324

```

325

326

### S2StringContext1

327

328

Minimal string interpolation.

329

330

```scala { .api }

331

trait S2StringContext1 {

332

implicit class S2StringContext1(sc: StringContext) {

333

def s2(args: Any*): Fragments

334

}

335

}

336

```

337

338

## Advanced DSL Features

339

340

### Auto Examples

341

342

Automatically capture code as examples:

343

344

```scala { .api }

345

trait AutoExamples {

346

def eg[T: AsResult](code: T): Fragment

347

}

348

```

349

350

**Usage:**

351

```scala

352

class AutoExampleSpec extends Specification with AutoExamples { def is = s2"""

353

Auto-captured examples

354

${eg { calculator.add(2, 3) must beEqualTo(5) }}

355

${eg { list.filter(_ > 0) must contain(exactly(1, 2, 3)) }}

356

"""

357

}

358

```

359

360

### Snippets

361

362

Extract and display code snippets in specifications:

363

364

```scala { .api }

365

trait Snippets {

366

def snippet[T](code: => T): Fragment

367

def eval[T](code: => T): Fragment

368

}

369

```

370

371

**Usage:**

372

```scala

373

class SnippetSpec extends Specification with Snippets { def is = s2"""

374

Code examples

375

Basic usage:

376

${snippet {

377

val user = User("john", "john@test.com")

378

user.isValid must beTrue

379

}}

380

381

Advanced usage:

382

${eval {

383

val users = loadUsers()

384

users.filter(_.active) must haveSize(expectedCount)

385

}}

386

"""

387

}

388

```

389

390

## DSL Composition Patterns

391

392

### Combining DSL Traits

393

394

Create custom DSL combinations:

395

396

```scala

397

trait MyCustomDsl extends AcceptanceDsl1

398

with TagDsl

399

with ActionDsl {

400

401

// Custom DSL methods

402

def setup(action: => Any) = step(action)

403

def cleanup(action: => Any) = step(action)

404

405

def fastTest[T: AsResult](body: => T) =

406

(body must not(throwAn[Exception])) ^ tag("fast")

407

}

408

409

class CustomSpec extends Specification with MyCustomDsl { def is = s2"""

410

Custom DSL example

411

${setup(initializeDatabase())}

412

fast operation test ${fastTest { quickOperation() }}

413

${cleanup(shutdownDatabase())}

414

"""

415

}

416

```

417

418

### Specification Templates

419

420

Create reusable specification templates:

421

422

```scala

423

trait ServiceSpecTemplate extends Specification {

424

def serviceName: String

425

def service: Any

426

def validInput: Any

427

def invalidInput: Any

428

429

def is = s2"""

430

$serviceName service should

431

handle valid input $validCase

432

reject invalid input $invalidCase

433

be thread-safe $threadSafeCase

434

"""

435

436

def validCase: Result

437

def invalidCase: Result

438

def threadSafeCase: Result

439

}

440

441

class UserServiceSpec extends ServiceSpecTemplate {

442

def serviceName = "User"

443

def service = new UserService

444

def validInput = User("john", "john@test.com")

445

def invalidInput = User("", "invalid-email")

446

447

def validCase = service.create(validInput) must beSuccessful

448

def invalidCase = service.create(invalidInput) must beFailure

449

def threadSafeCase = {

450

val futures = (1 to 100).map(_ => Future(service.getCount))

451

Future.sequence(futures) must not(throwAn[Exception]).await

452

}

453

}

454

```

455

456

## Best Practices

457

458

1. **Use appropriate DSL level**: Choose between full (`AcceptanceDsl`) and minimal (`AcceptanceDsl1`) based on needs

459

2. **Structure with fragments**: Use `br`, `p`, `t`, `bt` for readable specification layout

460

3. **Tag strategically**: Use tags for test categorization and filtering

461

4. **Compose DSL traits**: Create custom DSL combinations for domain-specific needs

462

5. **Leverage string interpolation**: Use s2 strings for embedding examples directly

463

6. **Organize with sections**: Use `section` and `group` for logical organization

464

7. **Use steps wisely**: Apply `step` and `action` for setup/teardown at appropriate phases

465

8. **Template common patterns**: Create reusable specification templates for similar test structures