or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdindex.mdmocking.mdproperty-testing.mdtest-aspects.mdtest-environment.mdtest-execution.mdtest-specifications.md

test-execution.mddocs/

0

# Test Execution

1

2

Test runners and executors for running test suites with configurable behavior and reporting.

3

4

## Capabilities

5

6

### TestRunner

7

8

Main component for executing test specifications.

9

10

```scala { .api }

11

/**

12

* Test runner that executes test specifications

13

* @tparam R - Environment requirements

14

* @tparam E - Error type

15

*/

16

case class TestRunner[+R, -E](executor: TestExecutor[R, E]) {

17

/** Executes a test specification */

18

def run[R1 <: R, E1 >: E](spec: ZSpec[R1, E1]): URIO[R1, ExecutedSpec[E1]]

19

20

/** Creates new runner with different executor */

21

def withExecutor[R1, E1](executor: TestExecutor[R1, E1]): TestRunner[R1, E1]

22

}

23

24

object TestRunner {

25

/** Default test runner with standard test environment */

26

def default[R](testEnvironment: ZLayer[Any, Nothing, R]): TestRunner[R, Any]

27

}

28

```

29

30

### TestExecutor

31

32

Core execution engine for running tests with reporting.

33

34

```scala { .api }

35

/**

36

* Executes test specifications with configurable behavior

37

* @tparam R - Environment requirements

38

* @tparam E - Error type

39

*/

40

abstract class TestExecutor[-R, -E] {

41

/** Executes specification with reporter */

42

def run[R1 <: R, E1 >: E](

43

spec: ZSpec[R1, E1],

44

reporter: TestReporter[E1]

45

): URIO[R1, ExecutedSpec[E1]]

46

47

/** Executes specification with environment layer */

48

def runSpec[R1 <: R, E1 >: E](

49

spec: ZSpec[R1, E1],

50

environmentLayer: ZLayer[Any, Nothing, R1]

51

): UIO[ExecutedSpec[E1]]

52

}

53

54

object TestExecutor {

55

/** Default executor with standard configuration */

56

def default[R](testEnvironment: ZLayer[Any, Nothing, R]): TestExecutor[R, Any]

57

}

58

```

59

60

### Runnable Spec Base Classes

61

62

Abstract base classes for creating executable test specifications.

63

64

```scala { .api }

65

/**

66

* Base class for runnable test specifications

67

* @tparam R - Environment requirements

68

* @tparam E - Error type

69

*/

70

abstract class RunnableSpec[-R, +E] {

71

/** The test specification to run */

72

def spec: ZSpec[R, E]

73

74

/** Test runner configuration */

75

def runner: TestRunner[R, E]

76

77

/** Test aspects to apply to all tests */

78

def aspects: List[TestAspect[Nothing, R, Nothing, Any]]

79

80

/** Platform-specific configuration */

81

def platform: TestPlatform

82

83

/** Executes the specification */

84

def runSpec(spec: ZSpec[R, E]): URIO[R, ExecutedSpec[E]]

85

}

86

87

/**

88

* Default runnable spec with test environment

89

*/

90

abstract class DefaultRunnableSpec extends RunnableSpec[TestEnvironment, Any] {

91

/** Test specification with standard test environment */

92

def spec: ZSpec[TestEnvironment, Any]

93

94

/** Default aspects including timeout warning */

95

override def aspects: List[TestAspect[Nothing, TestEnvironment, Nothing, Any]] =

96

List(TestAspect.timeoutWarning(60.seconds))

97

98

/** Default test runner */

99

override def runner: TestRunner[TestEnvironment, Any] = defaultTestRunner

100

}

101

102

/**

103

* Mutable runnable spec for dynamic test creation

104

*/

105

abstract class MutableRunnableSpec extends RunnableSpec[TestEnvironment, Any] {

106

/** Mutable test specification */

107

def spec: ZSpec[TestEnvironment, Any]

108

}

109

```

110

111

### ExecutedSpec

112

113

Result of test execution with hierarchical structure.

114

115

```scala { .api }

116

/**

117

* Result of executing a test specification

118

* @tparam E - Error type

119

*/

120

case class ExecutedSpec[+E](

121

caseValue: SpecCase[Any, TestFailure[E], TestSuccess, ExecutedSpec[E]]

122

) {

123

/** Folds over the execution tree */

124

def fold[Z](f: ExecutedSpec[E] => Z): Z

125

126

/** Checks if any spec matches predicate */

127

def exists(f: ExecutedSpec[E] => Boolean): Boolean

128

129

/** Gets all failed specs */

130

def failures: List[ExecutedSpec[E]]

131

132

/** Gets all successful specs */

133

def successes: List[ExecutedSpec[E]]

134

135

/** Gets all ignored specs */

136

def ignored: List[ExecutedSpec[E]]

137

138

/** Counts total number of tests */

139

def size: Int

140

141

/** Transforms the execution result */

142

def transform[E1](f: SpecCase[Any, TestFailure[E], TestSuccess, ExecutedSpec[E]] =>

143

SpecCase[Any, TestFailure[E1], TestSuccess, ExecutedSpec[E1]]): ExecutedSpec[E1]

144

}

145

```

146

147

### Test Reporting

148

149

System for reporting test results with customizable output.

150

151

```scala { .api }

152

/**

153

* Reporter for test execution results

154

* @tparam E - Error type

155

*/

156

type TestReporter[-E] = (Duration, ExecutedSpec[E]) => URIO[TestLogger, Unit]

157

158

object TestReporter {

159

/** Silent reporter that produces no output */

160

val silent: TestReporter[Any]

161

}

162

163

/**

164

* Default test reporter with console output

165

*/

166

object DefaultTestReporter {

167

/** Standard console reporter */

168

def apply[E](duration: Duration, executedSpec: ExecutedSpec[E]): URIO[TestLogger, Unit]

169

}

170

```

171

172

### Summary and Results

173

174

Summary information about test execution.

175

176

```scala { .api }

177

/**

178

* Summary of test execution results

179

*/

180

case class Summary(

181

success: Int, // Number of successful tests

182

fail: Int, // Number of failed tests

183

ignore: Int, // Number of ignored tests

184

summary: String // Textual summary

185

) {

186

/** Total number of tests */

187

def total: Int = success + fail + ignore

188

189

/** Whether all tests passed */

190

def isSuccess: Boolean = fail == 0

191

}

192

193

object Summary {

194

/** Creates summary from executed spec */

195

def fromExecutedSpec[E](executedSpec: ExecutedSpec[E]): Summary

196

}

197

198

/**

199

* Builder for constructing test summaries

200

*/

201

class SummaryBuilder {

202

/** Adds successful test */

203

def addSuccess(): SummaryBuilder

204

205

/** Adds failed test */

206

def addFailure(): SummaryBuilder

207

208

/** Adds ignored test */

209

def addIgnored(): SummaryBuilder

210

211

/** Builds final summary */

212

def build(): Summary

213

}

214

```

215

216

### Platform Configuration

217

218

Platform-specific test execution configuration.

219

220

```scala { .api }

221

/**

222

* Platform-specific test configuration

223

*/

224

trait TestPlatform {

225

/** Whether platform is JVM */

226

def isJVM: Boolean

227

228

/** Whether platform is JavaScript */

229

def isJS: Boolean

230

231

/** Whether platform is Native */

232

def isNative: Boolean

233

234

/** Platform-specific test execution timeout */

235

def timeout: Duration

236

}

237

238

object TestPlatform {

239

/** Default platform configuration */

240

val default: TestPlatform

241

242

/** Check if running on JVM */

243

def isJVM: Boolean

244

245

/** Check if running on JavaScript */

246

def isJS: Boolean

247

248

/** Check if running on Native */

249

def isNative: Boolean

250

}

251

```

252

253

## Usage Examples

254

255

### Basic Runnable Spec

256

257

```scala

258

import zio.test._

259

import zio.test.environment.TestEnvironment

260

261

object BasicSpec extends DefaultRunnableSpec {

262

def spec = suite("Basic Tests")(

263

test("simple test") {

264

assert(2 + 2)(equalTo(4))

265

},

266

267

testM("effectful test") {

268

assertM(ZIO.succeed(42))(equalTo(42))

269

}

270

)

271

}

272

```

273

274

### Custom Runner Configuration

275

276

```scala

277

import zio.test._

278

import zio.duration._

279

280

object CustomRunnerSpec extends RunnableSpec[TestEnvironment, Any] {

281

def spec = suite("Custom Runner Tests")(

282

// test definitions...

283

)

284

285

override def aspects = List(

286

TestAspect.timeout(30.seconds),

287

TestAspect.parallel,

288

TestAspect.retryN(3)

289

)

290

291

override def runner = TestRunner(

292

TestExecutor.default(testEnvironment)

293

)

294

}

295

```

296

297

### Mutable Spec for Dynamic Tests

298

299

```scala

300

object DynamicSpec extends MutableRunnableSpec {

301

def spec = {

302

val dynamicTests = (1 to 5).map { i =>

303

test(s"dynamic test $i") {

304

assert(i * 2)(isGreaterThan(i))

305

}

306

}

307

308

suite("Dynamic Tests")(dynamicTests: _*)

309

}

310

}

311

```

312

313

### Custom Test Reporter

314

315

```scala

316

import zio.test._

317

318

val customReporter: TestReporter[Any] = (duration, executedSpec) => {

319

for {

320

summary <- ZIO.succeed(Summary.fromExecutedSpec(executedSpec))

321

_ <- TestLogger.logLine(s"Tests completed in ${duration.toMillis}ms")

322

_ <- TestLogger.logLine(s"Passed: ${summary.success}")

323

_ <- TestLogger.logLine(s"Failed: ${summary.fail}")

324

_ <- TestLogger.logLine(s"Ignored: ${summary.ignore}")

325

} yield ()

326

}

327

328

object CustomReporterSpec extends DefaultRunnableSpec {

329

def spec = suite("Custom Reporter Tests")(

330

// test definitions...

331

)

332

333

override def runner = TestRunner(

334

TestExecutor.default(testEnvironment)

335

).withReporter(customReporter)

336

}

337

```

338

339

### Platform-Specific Tests

340

341

```scala

342

object PlatformSpec extends DefaultRunnableSpec {

343

def spec = suite("Platform Tests")(

344

test("JVM only test") {

345

assertTrue(TestPlatform.isJVM)

346

} @@ TestAspect.jvmOnly,

347

348

test("JS only test") {

349

assertTrue(TestPlatform.isJS)

350

} @@ TestAspect.jsOnly,

351

352

suite("Cross-platform tests")(

353

test("works everywhere") {

354

assert(2 + 2)(equalTo(4))

355

}

356

)

357

)

358

}

359

```

360

361

### Running Tests Programmatically

362

363

```scala

364

import zio.test._

365

366

val mySpec = suite("Programmatic Tests")(

367

test("test 1")(assert(true)(isTrue)),

368

test("test 2")(assert(false)(isFalse))

369

)

370

371

val program = for {

372

runner <- ZIO.succeed(defaultTestRunner)

373

result <- runner.run(mySpec)

374

summary = Summary.fromExecutedSpec(result)

375

_ <- console.putStrLn(s"Tests: ${summary.total}, Passed: ${summary.success}")

376

} yield summary

377

378

// Run with test environment

379

program.provideLayer(testEnvironment ++ Console.live)

380

```

381

382

### Test Execution with Timeout

383

384

```scala

385

object TimeoutSpec extends DefaultRunnableSpec {

386

def spec = suite("Timeout Tests")(

387

testM("fast test") {

388

assertM(ZIO.succeed(42))(equalTo(42))

389

},

390

391

testM("slow test") {

392

for {

393

_ <- ZIO.sleep(10.seconds)

394

result <- ZIO.succeed(42)

395

} yield assert(result)(equalTo(42))

396

} @@ TestAspect.timeout(5.seconds)

397

)

398

399

override def aspects = List(

400

TestAspect.timeoutWarning(2.seconds)

401

)

402

}

403

```