or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdconfiguration.mdexceptions.mdfixtures.mdindex.mdtest-suites.mdtransforms.md

configuration.mddocs/

0

# Configuration

1

2

Test configuration classes and metadata types for organizing and controlling test execution. This includes test options, tags for categorizing tests, and source location tracking for error reporting.

3

4

## Capabilities

5

6

### TestOptions - Test Configuration

7

8

Configuration class for customizing individual test behavior including naming, tagging, and execution control.

9

10

```scala { .api }

11

/**

12

* Configuration options for individual tests

13

* @param name The test name

14

* @param tags Set of tags applied to the test

15

* @param location Source code location of the test

16

*/

17

final class TestOptions(val name: String, val tags: Set[Tag], val location: Location) extends Serializable {

18

19

/** Create a new TestOptions with a different name */

20

def withName(newName: String): TestOptions

21

22

/** Create a new TestOptions with different tags */

23

def withTags(newTags: Set[Tag]): TestOptions

24

25

/** Create a new TestOptions with a different location */

26

def withLocation(newLocation: Location): TestOptions

27

28

/** Add a single tag to this test */

29

def tag(t: Tag): TestOptions

30

31

// Convenience methods for common tags

32

/** Mark this test as expected to fail */

33

def fail: TestOptions

34

35

/** Mark this test as potentially flaky */

36

def flaky: TestOptions

37

38

/** Skip this test during execution */

39

def ignore: TestOptions

40

41

/** Mark this test as pending implementation */

42

def pending: TestOptions

43

44

/** Mark this test as pending with a comment */

45

def pending(comment: String): TestOptions

46

47

/** Run only this test (skip all others) */

48

def only: TestOptions

49

}

50

51

/**

52

* Companion object with factory methods

53

*/

54

object TestOptions extends TestOptionsConversions {

55

def apply(name: String)(implicit loc: Location): TestOptions

56

}

57

58

/**

59

* Implicit conversions for convenience

60

*/

61

trait TestOptionsConversions {

62

/** Convert a string to TestOptions with current location */

63

implicit def testOptionsFromString(name: String)(implicit loc: Location): TestOptions

64

}

65

```

66

67

**Usage Examples:**

68

69

```scala

70

class ConfigurationExamples extends FunSuite {

71

test("basic test") {

72

assert(true)

73

}

74

75

test("slow integration test".tag(Slow)) {

76

// This test is marked as slow

77

performIntegrationTest()

78

}

79

80

test("flaky network test".flaky) {

81

// This test may fail intermittently

82

callExternalAPI()

83

}

84

85

test("unimplemented feature".pending) {

86

// This test is not yet implemented

87

}

88

89

test("work in progress".pending("waiting for API changes")) {

90

// Pending with a specific reason

91

}

92

93

test("debug this specific test".only) {

94

// Only this test will run when debugging

95

assert(complexCondition())

96

}

97

98

// Combining multiple tags

99

test(TestOptions("comprehensive test")

100

.tag(Slow)

101

.tag(new Tag("integration"))) {

102

performComprehensiveTest()

103

}

104

}

105

```

106

107

### Test - Test Case Metadata

108

109

Metadata class representing a complete test case with all its configuration and execution details.

110

111

```scala { .api }

112

/**

113

* Complete test case with name, body, tags, and location

114

* @param name The test name

115

* @param body Function that executes the test and returns a Future

116

* @param tags Set of tags applied to this test

117

* @param location Source code location where test is defined

118

*/

119

final class Test(val name: String, val body: () => Future[Any], val tags: Set[Tag], val location: Location) extends Serializable {

120

121

/** Create a new test with a different name */

122

def withName(newName: String): Test

123

124

/** Create a new test with a different body */

125

def withBody(newBody: () => Future[Any]): Test

126

127

/** Create a new test with a transformed body */

128

def withBodyMap(newBody: Future[Any] => Future[Any]): Test

129

130

/** Create a new test with different tags */

131

def withTags(newTags: Set[Tag]): Test

132

133

/** Add a single tag to this test */

134

def tag(newTag: Tag): Test

135

136

/** Create a new test with a different location */

137

def withLocation(newLocation: Location): Test

138

139

/** Get annotations for this test (includes tags and location) */

140

def annotations: Array[Annotation]

141

}

142

```

143

144

### Tag - Test Categories

145

146

Tags for categorizing and controlling test execution behavior.

147

148

```scala { .api }

149

/**

150

* Base tag class for categorizing tests

151

* @param value The tag identifier string

152

*/

153

class Tag(val value: String) extends munit.internal.junitinterface.Tag with Annotation with Serializable

154

```

155

156

**Built-in Tags:**

157

158

```scala { .api }

159

// Pre-defined tags available in the munit package object

160

val Ignore = new Tag("Ignore") // Skip this test

161

val Only = new Tag("Only") // Run only this test

162

val Flaky = new Tag("Flaky") // Test may fail intermittently

163

val Fail = new Tag("Fail") // Test is expected to fail

164

val Pending: Tag with PendingTag = new Tag("Pending") with PendingTag // Test is pending implementation

165

val Slow = new Tag("Slow") // Test is slow running

166

167

/**

168

* Pending tag with custom comment

169

* @param value The comment explaining why test is pending

170

*/

171

case class PendingComment(override val value: String) extends Tag(value) with PendingCommentTag

172

```

173

174

**Usage Examples:**

175

176

```scala

177

class TagExamples extends FunSuite {

178

test("regular test") {

179

assert(true)

180

}

181

182

test("skip this test".tag(Ignore)) {

183

// This test will be skipped

184

fail("Should not run")

185

}

186

187

test("database test".tag(Slow).tag(new Tag("database"))) {

188

// Multiple tags can be applied

189

connectToDatabase()

190

}

191

192

// Custom tags

193

val Integration = new Tag("Integration")

194

val External = new Tag("External")

195

196

test("API integration".tag(Integration).tag(External)) {

197

callExternalAPI()

198

}

199

200

// Environment-specific tags

201

test("linux only test".tag(new Tag("linux"))) {

202

assume(System.getProperty("os.name").toLowerCase.contains("linux"))

203

// Test linux-specific functionality

204

}

205

}

206

```

207

208

### Location - Source Code Location

209

210

Source code location tracking for precise error reporting and IDE integration.

211

212

```scala { .api }

213

/**

214

* Source code location information

215

* @param path The file path where the test is defined

216

* @param line The line number in the file

217

*/

218

final class Location(val path: String, val line: Int) extends Annotation with Serializable {

219

220

/** Extract just the filename from the full path */

221

def filename: String

222

223

/** Format location as "path:line" */

224

override def toString: String

225

}

226

227

/**

228

* Companion object with utility methods

229

*/

230

object Location extends MacroCompat.LocationMacro {

231

/** Empty location placeholder for tests created programmatically */

232

def empty: Location

233

}

234

```

235

236

**Usage Examples:**

237

238

```scala

239

class LocationExamples extends FunSuite {

240

test("location is automatically captured") {

241

// Location is captured via macro at compile time

242

assert(true)

243

}

244

245

// Manual test creation with explicit location

246

val manualTest = new Test(

247

"manual test",

248

() => Future.successful(assert(true)),

249

Set.empty,

250

new Location("MyTest.scala", 42)

251

)

252

}

253

```

254

255

## Tag-Based Test Execution

256

257

### Environment Variables

258

259

MUnit respects several environment variables for controlling test execution:

260

261

- `MUNIT_FLAKY_OK`: Set to allow flaky tests to pass even if they fail

262

- `CI`: Detected automatically to adjust behavior in continuous integration

263

264

### Test Filtering

265

266

Tags can be used with build tools and IDEs to filter which tests run:

267

268

```scala

269

// Run only slow tests

270

sbt 'testOnly -- --include-tags=Slow'

271

272

// Exclude flaky tests

273

sbt 'testOnly -- --exclude-tags=Flaky'

274

275

// Run tests with multiple tags

276

sbt 'testOnly -- --include-tags=Integration,Database'

277

```

278

279

### Custom Tag Patterns

280

281

Create domain-specific tags for your project:

282

283

```scala

284

object TestTags {

285

val Unit = new Tag("Unit")

286

val Integration = new Tag("Integration")

287

val Performance = new Tag("Performance")

288

val Security = new Tag("Security")

289

val UI = new Tag("UI")

290

val API = new Tag("API")

291

}

292

293

class ServiceTests extends FunSuite {

294

import TestTags._

295

296

test("unit test".tag(Unit)) {

297

// Fast unit test

298

}

299

300

test("integration test".tag(Integration).tag(Slow)) {

301

// Slower integration test

302

}

303

304

test("performance benchmark".tag(Performance).tag(Slow)) {

305

// Performance testing

306

}

307

}

308

```

309

310

### Compare - Type-Safe Comparisons

311

312

Type-class that enables type-safe comparisons in MUnit assertions with custom failure handling.

313

314

```scala { .api }

315

/**

316

* Type-class for comparing values in MUnit assertions

317

* Enables type-safe comparisons between related types

318

*/

319

trait Compare[A, B] {

320

321

/** Check if two values are equal according to comparison rules */

322

def isEqual(obtained: A, expected: B): Boolean

323

324

/** Handle comparison failures with custom error messages and diff output */

325

def failEqualsComparison(obtained: A, expected: B, title: Any, assertions: Assertions)(implicit loc: Location, options: DiffOptions): Nothing

326

}

327

328

/**

329

* Companion object providing default comparison implementations

330

*/

331

object Compare extends ComparePriority1 {

332

/** Default comparison using == for any two types */

333

def defaultCompare[A, B]: Compare[A, B]

334

}

335

336

/**

337

* Implicit priority for subtype comparisons

338

*/

339

trait ComparePriority1 extends ComparePriority2 {

340

/** Allow comparison when A is a subtype of B */

341

implicit def compareSubtypeWithSupertype[A, B](implicit ev: A <:< B): Compare[A, B]

342

}

343

344

/**

345

* Implicit priority for supertype comparisons

346

*/

347

trait ComparePriority2 {

348

/** Allow comparison when B is a subtype of A */

349

implicit def compareSupertypeWithSubtype[A, B](implicit ev: A <:< B): Compare[B, A]

350

}

351

```

352

353

**Usage Examples:**

354

355

```scala

356

// Custom comparison for domain objects

357

implicit val userCompare: Compare[User, User] = new Compare[User, User] {

358

def isEqual(obtained: User, expected: User): Boolean =

359

obtained.id == expected.id && obtained.email == expected.email

360

361

def failEqualsComparison(obtained: User, expected: User, title: Any, assertions: Assertions)(implicit loc: Location, options: DiffOptions): Nothing =

362

assertions.failComparison(s"Users not equal: $title", obtained, expected)

363

}

364

365

class UserTests extends FunSuite {

366

test("user equality") {

367

val user1 = User(1, "alice@example.com", "Alice")

368

val user2 = User(1, "alice@example.com", "Alice Smith") // Different name

369

assertEquals(user1, user2) // Uses custom comparison (ignores name)

370

}

371

}

372

```

373

374

### Printable - Custom Pretty-Printing

375

376

Interface for customizing how values are displayed in test failure messages.

377

378

```scala { .api }

379

/**

380

* Interface for objects that can customize their printed representation

381

*/

382

trait Printable {

383

/** Append custom representation to a StringBuilder */

384

def print(out: StringBuilder, indent: Int): Unit

385

}

386

```

387

388

**Usage Examples:**

389

390

```scala

391

case class ComplexData(values: Map[String, Any]) extends Printable {

392

def print(out: StringBuilder, indent: Int): Unit = {

393

out.append("ComplexData(\n")

394

values.foreach { case (key, value) =>

395

out.append(" " * (indent + 1))

396

out.append(s"$key = $value\n")

397

}

398

out.append(" " * indent)

399

out.append(")")

400

}

401

}

402

403

class PrintableTests extends FunSuite {

404

test("complex data comparison") {

405

val data1 = ComplexData(Map("x" -> 1, "y" -> 2))

406

val data2 = ComplexData(Map("x" -> 1, "y" -> 3))

407

408

// Custom printing will be used in failure message

409

assertEquals(data1, data2)

410

}

411

}

412

```

413

414

### MUnitRunner - Test Framework Integration

415

416

JUnit runner that enables MUnit integration with IDEs and build tools.

417

418

```scala { .api }

419

/**

420

* JUnit runner for MUnit test suites

421

* Automatically applied to Suite classes via @RunWith annotation

422

*/

423

class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) extends Runner

424

425

/**

426

* Companion object with runner utilities

427

*/

428

object MUnitRunner {

429

/** Create a runner for a suite class */

430

def apply(cls: Class[_ <: Suite]): MUnitRunner

431

}

432

```

433

434

**Usage:**

435

436

```scala

437

// Automatically applied to all Suite subclasses

438

@RunWith(classOf[MUnitRunner])

439

abstract class Suite extends PlatformSuite {

440

// Suite implementation

441

}