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

mutable-specifications.mddocs/

0

# Mutable Specifications

1

2

Mutable specifications provide an imperative-style API for writing tests where examples are defined using side-effects and thrown expectations. This style is familiar to developers coming from traditional unit testing frameworks like JUnit or ScalaTest.

3

4

## Mutable Specification Classes

5

6

### Specification (mutable)

7

8

Main mutable specification class using thrown expectations.

9

10

```scala { .api }

11

// org.specs2.mutable

12

abstract class Specification extends SpecificationLike

13

```

14

15

**Usage Example:**

16

```scala

17

import org.specs2.mutable._

18

19

class CalculatorSpec extends Specification {

20

"Calculator" should {

21

"add two numbers" in {

22

val calc = new Calculator

23

calc.add(2, 3) must beEqualTo(5)

24

}

25

26

"subtract two numbers" in {

27

val calc = new Calculator

28

calc.subtract(5, 2) must beEqualTo(3)

29

}

30

31

"handle division by zero" in {

32

val calc = new Calculator

33

calc.divide(1, 0) must throwA[ArithmeticException]

34

}

35

}

36

}

37

```

38

39

### SpecificationLike (mutable)

40

41

Core mutable specification trait.

42

43

```scala { .api }

44

trait SpecificationLike extends SpecificationStructure

45

with SpecificationCreation

46

with SpecificationFeatures

47

```

48

49

Provides mutable-specific implementations of:

50

- Example creation with side-effects

51

- Thrown expectations on failures

52

- Imperative specification building

53

54

### Spec (mutable)

55

56

Lightweight mutable specification class.

57

58

```scala { .api }

59

abstract class Spec extends SpecLike

60

```

61

62

**Usage Example:**

63

```scala

64

import org.specs2.mutable._

65

66

class SimpleSpec extends Spec {

67

"Simple test" should {

68

"pass" in {

69

1 + 1 must beEqualTo(2)

70

}

71

}

72

}

73

```

74

75

### SpecLike (mutable)

76

77

Lightweight mutable specification trait.

78

79

```scala { .api }

80

trait SpecLike extends SpecificationStructure

81

with ExampleDsl0

82

with MustThrownMatchers1

83

```

84

85

Includes:

86

- `ExampleDsl0`: Basic example creation methods

87

- `MustThrownMatchers1`: Core matchers with thrown expectations

88

89

## Mutable DSL Components

90

91

### ExampleDsl (mutable)

92

93

DSL for creating examples in mutable specifications.

94

95

```scala { .api }

96

trait ExampleDsl {

97

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

98

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

99

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

100

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

101

}

102

```

103

104

### TextDsl (mutable)

105

106

Adding descriptive text to mutable specifications.

107

108

```scala { .api }

109

trait TextDsl {

110

def br: Unit

111

def p: Unit

112

def tab: Unit

113

def backtab: Unit

114

def end: Unit

115

}

116

```

117

118

### MutableFragmentBuilder

119

120

Building specification structure imperatively.

121

122

```scala { .api }

123

trait MutableFragmentBuilder {

124

def addFragment(fragment: Fragment): Unit

125

def addText(text: String): Unit

126

def addExample(description: String, body: => Any): Unit

127

def addStep(action: => Any): Unit

128

}

129

```

130

131

## Thrown Expectations

132

133

### MustThrownMatchers

134

135

Matchers that throw exceptions on failure (for mutable specs).

136

137

```scala { .api }

138

trait MustThrownMatchers extends MustMatchers {

139

override def createExpectation[T](t: => T): Expectable[T]

140

override def checkFailure[T](m: MatchResult[T]): MatchResult[T]

141

}

142

```

143

144

### ShouldThrownMatchers

145

146

Alternative "should" syntax with thrown expectations.

147

148

```scala { .api }

149

trait ShouldThrownMatchers extends ShouldMatchers {

150

override def createExpectation[T](t: => T): Expectable[T]

151

override def checkFailure[T](m: MatchResult[T]): MatchResult[T]

152

}

153

```

154

155

## Mutable Specification Structure

156

157

### SpecificationStructure (mutable)

158

159

Mutable specification structure management.

160

161

```scala { .api }

162

trait SpecificationStructure {

163

protected var specFragments: Vector[Fragment] = Vector.empty

164

165

def addFragment(f: Fragment): Unit

166

def prependFragment(f: Fragment): Unit

167

def content: Fragments

168

}

169

```

170

171

### MutableSpecificationStructure

172

173

Enhanced mutable structure with modification methods.

174

175

```scala { .api }

176

trait MutableSpecificationStructure extends SpecificationStructure {

177

def insertFragment(index: Int, f: Fragment): Unit

178

def removeFragment(index: Int): Unit

179

def replaceFragment(index: Int, f: Fragment): Unit

180

def clearFragments(): Unit

181

}

182

```

183

184

## Context Support

185

186

### BeforeEach (mutable)

187

188

Setup actions before each example.

189

190

```scala { .api }

191

trait BeforeEach {

192

def before: Any

193

194

def apply[T: AsResult](a: => T): Result = {

195

before

196

AsResult(a)

197

}

198

}

199

```

200

201

### AfterEach (mutable)

202

203

Cleanup actions after each example.

204

205

```scala { .api }

206

trait AfterEach {

207

def after: Any

208

209

def apply[T: AsResult](a: => T): Result = {

210

try AsResult(a)

211

finally after

212

}

213

}

214

```

215

216

### AroundEach (mutable)

217

218

Wrap each example with custom logic.

219

220

```scala { .api }

221

trait AroundEach {

222

def around[T: AsResult](t: => T): Result

223

224

def apply[T: AsResult](a: => T): Result = around(a)

225

}

226

```

227

228

### BeforeAfterEach

229

230

Combined setup and cleanup.

231

232

```scala { .api }

233

trait BeforeAfterEach extends BeforeEach with AfterEach {

234

def apply[T: AsResult](a: => T): Result = {

235

before

236

try AsResult(a)

237

finally after

238

}

239

}

240

```

241

242

## Advanced Mutable Features

243

244

### Specification Scoping

245

246

Nested specification structure:

247

248

```scala

249

class DatabaseSpec extends Specification {

250

"Database operations" should {

251

"User operations" should {

252

"create users" in { /* test */ }

253

"update users" in { /* test */ }

254

"delete users" in { /* test */ }

255

}

256

257

"Order operations" should {

258

"create orders" in { /* test */ }

259

"process orders" in { /* test */ }

260

}

261

}

262

}

263

```

264

265

### Specification Arguments (mutable)

266

267

Configure mutable specification behavior:

268

269

```scala { .api }

270

trait ArgumentsShortcuts {

271

def sequential: Arguments

272

def isolated: Arguments

273

def stopOnFail: Arguments

274

def plan: Arguments

275

def skipAll: Arguments

276

}

277

```

278

279

### Tags and Sections (mutable)

280

281

Organizing and filtering examples:

282

283

```scala { .api }

284

trait TagDsl {

285

def tag(names: String*): Unit

286

def section(name: String): Unit

287

}

288

```

289

290

**Usage:**

291

```scala

292

class TaggedSpec extends Specification {

293

"Feature X" should {

294

"work in normal cases" in {

295

// test code

296

} tag("unit", "fast")

297

298

"work under load" in {

299

// test code

300

} tag("integration", "slow")

301

}

302

}

303

```

304

305

## Usage Patterns

306

307

### Basic Mutable Pattern

308

309

```scala

310

import org.specs2.mutable._

311

312

class UserServiceSpec extends Specification {

313

"UserService" should {

314

val service = new UserService

315

316

"create new users" in {

317

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

318

user.name must beEqualTo("john")

319

user.email must beEqualTo("john@test.com")

320

}

321

322

"find users by email" in {

323

service.create("jane", "jane@test.com")

324

val found = service.findByEmail("jane@test.com")

325

found must beSome.which(_.name == "jane")

326

}

327

}

328

}

329

```

330

331

### Setup and Teardown

332

333

```scala

334

class DatabaseSpec extends Specification with BeforeAfterEach {

335

def before = {

336

Database.createTables()

337

Database.seedTestData()

338

}

339

340

def after = {

341

Database.cleanup()

342

}

343

344

"Database operations" should {

345

"insert records" in {

346

val count = Database.insert(testRecord)

347

count must beEqualTo(1)

348

}

349

350

"query records" in {

351

val results = Database.query("SELECT * FROM users")

352

results must not(beEmpty)

353

}

354

}

355

}

356

```

357

358

### Shared Examples

359

360

```scala

361

trait UserBehavior {

362

def validUser = {

363

"have a valid name" in {

364

user.name must not(beEmpty)

365

}

366

367

"have a valid email" in {

368

user.email must beMatching(emailRegex)

369

}

370

}

371

372

def user: User

373

def emailRegex: String

374

}

375

376

class UserSpec extends Specification with UserBehavior {

377

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

378

def emailRegex = ".*@.*\\..*"

379

380

"User" should {

381

validUser

382

383

"calculate age correctly" in {

384

user.copy(birthYear = 1990).age must beGreaterThan(30)

385

}

386

}

387

}

388

```

389

390

### Conditional Examples

391

392

```scala

393

class ConditionalSpec extends Specification {

394

"Feature" should {

395

if (System.getProperty("integration.tests") == "true") {

396

"work with external service" in {

397

// integration test code

398

}

399

}

400

401

"work offline" in {

402

// unit test code

403

}

404

}

405

}

406

```

407

408

## Best Practices

409

410

1. **Use descriptive nesting**: Create logical hierarchies with nested "should" blocks

411

2. **Keep setup minimal**: Use context traits for complex setup/teardown scenarios

412

3. **Group related tests**: Use nested structure to group related functionality

413

4. **Avoid shared mutable state**: Each example should be independent

414

5. **Use tags wisely**: Tag examples for filtering slow or integration tests

415

6. **Handle exceptions properly**: Use appropriate matchers for expected exceptions

416

7. **Document with text**: Add descriptive text blocks to explain complex scenarios