or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions-matchers.mdasync-testing.mdindex.mdscalactic-utilities.mdtest-execution.mdtest-styles.md

test-styles.mddocs/

0

# Test Styles

1

2

ScalaTest provides eight different testing styles to accommodate various preferences and use cases. Each style offers a different syntax and organization approach while sharing the same underlying framework capabilities.

3

4

## Capabilities

5

6

### FunSuite Style

7

8

Function-based testing where each test is defined as a function with a descriptive name.

9

10

```scala { .api }

11

import org.scalatest.funsuite.AnyFunSuite

12

import org.scalatest.Tag

13

14

class MyFunSuite extends AnyFunSuite {

15

protected def test(testName: String, testTags: Tag*)(testFun: => Any): Unit

16

protected def ignore(testName: String, testTags: Tag*)(testFun: => Any): Unit

17

}

18

19

// Async version

20

import org.scalatest.funsuite.AsyncFunSuite

21

import scala.concurrent.Future

22

class MyAsyncFunSuite extends AsyncFunSuite {

23

protected def test(testName: String, testTags: Tag*)(testFun: => Future[compatible.Assertion]): Unit

24

}

25

26

// Fixture versions

27

import org.scalatest.funsuite.FixtureAnyFunSuite

28

class MyFixtureFunSuite extends FixtureAnyFunSuite {

29

type FixtureParam = MyFixture

30

def withFixture(test: OneArgTest): Outcome

31

}

32

```

33

34

**Usage Example:**

35

```scala

36

import org.scalatest.funsuite.AnyFunSuite

37

38

class CalculatorSuite extends AnyFunSuite {

39

test("addition should work") {

40

assert(2 + 2 === 4)

41

}

42

43

test("subtraction should work") {

44

assert(4 - 2 === 2)

45

}

46

47

ignore("temporarily disabled test") {

48

// This test will be ignored

49

assert(1 === 2)

50

}

51

}

52

```

53

54

### FlatSpec Style

55

56

BDD-style flat specification with "should" or "must" syntax.

57

58

```scala { .api }

59

import org.scalatest.flatspec.AnyFlatSpec

60

61

class MyFlatSpec extends AnyFlatSpec {

62

behavior of "subject"

63

"it" should "behavior description" in { /* test code */ }

64

"they" should "behavior description" in { /* test code */ }

65

ignore should "ignored behavior" in { /* test code */ }

66

}

67

68

// Async version

69

import org.scalatest.flatspec.AsyncFlatSpec

70

class MyAsyncFlatSpec extends AsyncFlatSpec {

71

"it" should "behavior description" in {

72

Future { assert(true) }

73

}

74

}

75

```

76

77

**Usage Example:**

78

```scala

79

import org.scalatest.flatspec.AnyFlatSpec

80

import org.scalatest.matchers.should.Matchers

81

82

class StackSpec extends AnyFlatSpec with Matchers {

83

behavior of "A Stack"

84

85

it should "pop values in last-in-first-out order" in {

86

val stack = new Stack[Int]

87

stack.push(1)

88

stack.push(2)

89

stack.pop() should be(2)

90

stack.pop() should be(1)

91

}

92

93

it should "throw NoSuchElementException if an empty stack is popped" in {

94

val emptyStack = new Stack[Int]

95

a [NoSuchElementException] should be thrownBy {

96

emptyStack.pop()

97

}

98

}

99

}

100

```

101

102

### WordSpec Style

103

104

Nested specification style using "when" and "should" for organization.

105

106

```scala { .api }

107

import org.scalatest.wordspec.AnyWordSpec

108

109

class MyWordSpec extends AnyWordSpec {

110

"subject" when {

111

"condition" should {

112

"behavior" in { /* test code */ }

113

}

114

}

115

116

"subject" should {

117

"behavior" in { /* test code */ }

118

}

119

}

120

121

// Async version

122

import org.scalatest.wordspec.AsyncWordSpec

123

class MyAsyncWordSpec extends AsyncWordSpec {

124

"subject" should {

125

"behavior" in {

126

Future { assert(true) }

127

}

128

}

129

}

130

```

131

132

**Usage Example:**

133

```scala

134

import org.scalatest.wordspec.AnyWordSpec

135

import org.scalatest.matchers.should.Matchers

136

137

class StackSpec extends AnyWordSpec with Matchers {

138

"A Stack" when {

139

"empty" should {

140

"be empty" in {

141

val stack = new Stack[Int]

142

stack.isEmpty should be(true)

143

}

144

145

"throw NoSuchElementException when popped" in {

146

val stack = new Stack[Int]

147

a [NoSuchElementException] should be thrownBy {

148

stack.pop()

149

}

150

}

151

}

152

153

"non-empty" should {

154

"return the correct size" in {

155

val stack = new Stack[Int]

156

stack.push(1)

157

stack.push(2)

158

stack.size should be(2)

159

}

160

}

161

}

162

}

163

```

164

165

### FreeSpec Style

166

167

Free-form specification style using dash (-) syntax for nesting.

168

169

```scala { .api }

170

import org.scalatest.freespec.AnyFreeSpec

171

172

class MyFreeSpec extends AnyFreeSpec {

173

"description" - {

174

"nested description" - {

175

"test description" in { /* test code */ }

176

}

177

"another test" in { /* test code */ }

178

}

179

}

180

181

// Async version

182

import org.scalatest.freespec.AsyncFreeSpec

183

class MyAsyncFreeSpec extends AsyncFreeSpec {

184

"description" - {

185

"test" in {

186

Future { assert(true) }

187

}

188

}

189

}

190

191

// Path-dependent version (creates new instance for each test)

192

import org.scalatest.freespec.PathAnyFreeSpec

193

class MyPathFreeSpec extends PathAnyFreeSpec {

194

"subject" - {

195

"when condition" - {

196

"should behavior" in {

197

// Each test gets a fresh instance

198

assert(true)

199

}

200

}

201

}

202

}

203

```

204

205

**Usage Example:**

206

```scala

207

import org.scalatest.freespec.AnyFreeSpec

208

import org.scalatest.matchers.should.Matchers

209

210

class StackSpec extends AnyFreeSpec with Matchers {

211

"A Stack" - {

212

"when empty" - {

213

"should be empty" in {

214

val stack = new Stack[Int]

215

stack.isEmpty should be(true)

216

}

217

218

"should throw exception when popped" in {

219

val stack = new Stack[Int]

220

a [NoSuchElementException] should be thrownBy {

221

stack.pop()

222

}

223

}

224

}

225

226

"when containing elements" - {

227

"should not be empty" in {

228

val stack = new Stack[Int]

229

stack.push(1)

230

stack.isEmpty should be(false)

231

}

232

}

233

}

234

}

235

```

236

237

### FeatureSpec Style

238

239

BDD-style feature specification with "feature" and "scenario" keywords.

240

241

```scala { .api }

242

import org.scalatest.featurespec.AnyFeatureSpec

243

244

class MyFeatureSpec extends AnyFeatureSpec {

245

feature("feature description") {

246

scenario("scenario description") { /* test code */ }

247

ignore("ignored scenario") { /* test code */ }

248

}

249

}

250

251

// Async version

252

import org.scalatest.featurespec.AsyncFeatureSpec

253

class MyAsyncFeatureSpec extends AsyncFeatureSpec {

254

feature("feature") {

255

scenario("scenario") {

256

Future { assert(true) }

257

}

258

}

259

}

260

```

261

262

**Usage Example:**

263

```scala

264

import org.scalatest.featurespec.AnyFeatureSpec

265

import org.scalatest.matchers.should.Matchers

266

267

class CalculatorSpec extends AnyFeatureSpec with Matchers {

268

feature("Calculator arithmetic operations") {

269

scenario("User adds two positive numbers") {

270

val calculator = new Calculator

271

val result = calculator.add(2, 3)

272

result should be(5)

273

}

274

275

scenario("User divides by zero") {

276

val calculator = new Calculator

277

a [ArithmeticException] should be thrownBy {

278

calculator.divide(10, 0)

279

}

280

}

281

}

282

283

feature("Calculator memory functions") {

284

scenario("User stores and recalls a value") {

285

val calculator = new Calculator

286

calculator.store(42)

287

calculator.recall() should be(42)

288

}

289

}

290

}

291

```

292

293

### FunSpec Style

294

295

RSpec-style specification with "describe" and "it" blocks.

296

297

```scala { .api }

298

import org.scalatest.funspec.AnyFunSpec

299

300

class MyFunSpec extends AnyFunSpec {

301

describe("subject") {

302

it("behavior description") { /* test code */ }

303

ignore("ignored behavior") { /* test code */ }

304

305

describe("nested subject") {

306

it("nested behavior") { /* test code */ }

307

}

308

}

309

}

310

311

// Async version

312

import org.scalatest.funspec.AsyncFunSpec

313

class MyAsyncFunSpec extends AsyncFunSpec {

314

describe("subject") {

315

it("behavior") {

316

Future { assert(true) }

317

}

318

}

319

}

320

321

// Path-dependent version (creates new instance for each test)

322

import org.scalatest.funspec.PathAnyFunSpec

323

class MyPathFunSpec extends PathAnyFunSpec {

324

describe("subject") {

325

it("behavior description") {

326

// Each test gets a fresh instance

327

assert(true)

328

}

329

330

describe("nested subject") {

331

it("nested behavior") {

332

assert(true)

333

}

334

}

335

}

336

}

337

```

338

339

**Usage Example:**

340

```scala

341

import org.scalatest.funspec.AnyFunSpec

342

import org.scalatest.matchers.should.Matchers

343

344

class StackSpec extends AnyFunSpec with Matchers {

345

describe("A Stack") {

346

describe("when empty") {

347

it("should be empty") {

348

val stack = new Stack[Int]

349

stack.isEmpty should be(true)

350

}

351

352

it("should throw exception when popped") {

353

val stack = new Stack[Int]

354

a [NoSuchElementException] should be thrownBy {

355

stack.pop()

356

}

357

}

358

}

359

360

describe("when it has one item") {

361

it("should have size 1") {

362

val stack = new Stack[Int]

363

stack.push(9)

364

stack.size should be(1)

365

}

366

}

367

}

368

}

369

```

370

371

### PropSpec Style

372

373

Property-based testing style for defining properties that should hold for ranges of data.

374

375

```scala { .api }

376

import org.scalatest.propspec.AnyPropSpec

377

378

class MyPropSpec extends AnyPropSpec {

379

property("property description") { /* test code */ }

380

ignore("ignored property") { /* test code */ }

381

}

382

383

// Async version

384

import org.scalatest.propspec.AsyncPropSpec

385

class MyAsyncPropSpec extends AsyncPropSpec {

386

property("property") {

387

Future { assert(true) }

388

}

389

}

390

```

391

392

**Usage Example:**

393

```scala

394

import org.scalatest.propspec.AnyPropSpec

395

import org.scalatest.matchers.should.Matchers

396

397

class StringSpec extends AnyPropSpec with Matchers {

398

property("string concatenation is associative") {

399

val a = "hello"

400

val b = " "

401

val c = "world"

402

(a + b) + c should equal(a + (b + c))

403

}

404

405

property("string length is additive for concatenation") {

406

val s1 = "hello"

407

val s2 = "world"

408

val combined = s1 + s2

409

combined.length should equal(s1.length + s2.length)

410

}

411

}

412

```

413

414

### RefSpec Style

415

416

Reflection-based specification style where test methods are identified by naming convention.

417

418

```scala { .api }

419

import org.scalatest.refspec.RefSpec

420

421

class MyRefSpec extends RefSpec {

422

// Methods starting with "test" are test methods

423

def `test: description`(): Unit = { /* test code */ }

424

def testDescription(): Unit = { /* test code */ }

425

426

// Methods starting with "ignore" are ignored

427

def `ignore: description`(): Unit = { /* test code */ }

428

}

429

```

430

431

**Usage Example:**

432

```scala

433

import org.scalatest.refspec.RefSpec

434

import org.scalatest.matchers.should.Matchers

435

436

class StackRefSpec extends RefSpec with Matchers {

437

def `test: empty stack should be empty`(): Unit = {

438

val stack = new Stack[Int]

439

stack.isEmpty should be(true)

440

}

441

442

def `test: stack should pop in LIFO order`(): Unit = {

443

val stack = new Stack[Int]

444

stack.push(1)

445

stack.push(2)

446

stack.pop() should be(2)

447

stack.pop() should be(1)

448

}

449

450

def `ignore: temporarily disabled test`(): Unit = {

451

// This test will be ignored

452

assert(false)

453

}

454

}

455

```

456

457

## Fixture Support

458

459

All test styles support fixture variants for managing test resources:

460

461

```scala { .api }

462

// Fixture variants exist for all styles

463

import org.scalatest.funsuite.FixtureAnyFunSuite

464

import org.scalatest.flatspec.FixtureAnyFlatSpec

465

import org.scalatest.wordspec.FixtureAnyWordSpec

466

// ... and so on

467

468

abstract class FixtureTestSuite extends FixtureAnyFunSuite {

469

type FixtureParam = YourFixtureType

470

471

def withFixture(test: OneArgTest): Outcome = {

472

// Setup fixture

473

val fixture = createFixture()

474

try {

475

test(fixture)

476

} finally {

477

// Cleanup fixture

478

cleanupFixture(fixture)

479

}

480

}

481

}

482

```

483

484

## Choosing a Test Style

485

486

- **FunSuite**: Simple function-based tests, good for unit testing

487

- **FlatSpec**: BDD-style with flat organization, good for behavior specification

488

- **WordSpec**: Nested BDD-style with hierarchical organization

489

- **FreeSpec**: Maximum flexibility in organization and nesting

490

- **FeatureSpec**: Feature/scenario BDD style, good for acceptance testing

491

- **FunSpec**: RSpec-style describe/it blocks, familiar to Ruby developers

492

- **PropSpec**: Property-based testing, good for testing invariants

493

- **RefSpec**: Reflection-based, familiar to JUnit users

494

495

All styles can be mixed in a single test suite and share the same assertion and matcher capabilities.

496

497

### Path-Dependent Testing

498

499

FreeSpec and FunSpec support path-dependent variants (`PathAnyFreeSpec`, `PathAnyFunSpec`) that create a new instance of the test class for each test. This provides:

500

501

- **Test Isolation**: Each test runs in a completely fresh instance

502

- **Shared Setup**: Instance variables can be used for test setup without interference

503

- **Stateful Testing**: Safer when tests modify instance state

504

505

Use path-dependent styles when you need strong test isolation or have complex shared setup requirements.