or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdconfiguration.mdindex.mdproperty-testing.mdtest-aspects.mdtest-definition.mdtest-services.md

configuration.mddocs/

0

# Configuration and Environment

1

2

Configuration system for controlling test execution parameters and environment setup for dependency injection.

3

4

## Capabilities

5

6

### TestConfig

7

8

Configuration service that controls various aspects of test execution.

9

10

```scala { .api }

11

/**

12

* Configuration for test execution parameters

13

*/

14

trait TestConfig {

15

/**

16

* Number of times to repeat each test

17

* @return number of repetitions

18

*/

19

def repeats: Int

20

21

/**

22

* Number of times to retry failed tests

23

* @return number of retries

24

*/

25

def retries: Int

26

27

/**

28

* Number of samples for property-based tests

29

* @return number of samples to generate

30

*/

31

def samples: Int

32

33

/**

34

* Maximum shrinking attempts for failed property tests

35

* @return maximum shrinking attempts

36

*/

37

def shrinks: Int

38

39

/**

40

* Size parameter for generators

41

* @return size value for Sized environment

42

*/

43

def size: Int

44

}

45

46

object TestConfig {

47

/**

48

* Create test configuration with specified parameters

49

* @param repeats number of test repetitions

50

* @param retries number of retry attempts

51

* @param samples number of property test samples

52

* @param shrinks maximum shrinking attempts

53

* @param size generator size parameter

54

* @return layer providing test configuration

55

*/

56

def live(

57

repeats: Int,

58

retries: Int,

59

samples: Int,

60

shrinks: Int,

61

size: Int

62

): ULayer[TestConfig]

63

64

/**

65

* Default test configuration

66

* - repeats: 1

67

* - retries: 0

68

* - samples: 200

69

* - shrinks: 1000

70

* - size: 100

71

*/

72

val default: ULayer[TestConfig]

73

74

/**

75

* Access number of repeats from configuration

76

*/

77

val repeats: URIO[TestConfig, Int]

78

79

/**

80

* Access number of retries from configuration

81

*/

82

val retries: URIO[TestConfig, Int]

83

84

/**

85

* Access number of samples from configuration

86

*/

87

val samples: URIO[TestConfig, Int]

88

89

/**

90

* Access number of shrinks from configuration

91

*/

92

val shrinks: URIO[TestConfig, Int]

93

94

/**

95

* Access size parameter from configuration

96

*/

97

val size: URIO[TestConfig, Int]

98

}

99

```

100

101

**Usage Examples:**

102

103

```scala

104

import zio.test._

105

import zio._

106

107

// Custom test configuration

108

val customConfig = TestConfig.live(

109

repeats = 5, // Run each test 5 times

110

retries = 2, // Retry failed tests twice

111

samples = 1000, // Use 1000 samples for property tests

112

shrinks = 500, // Maximum 500 shrinking attempts

113

size = 200 // Generator size of 200

114

)

115

116

// Using configuration in tests

117

test("property test with custom config").provideLayer(customConfig) {

118

check(Gen.listOf(Gen.anyInt)) { list =>

119

assertTrue(list.reverse.reverse == list)

120

}

121

}

122

123

// Access configuration values

124

test("configuration access") {

125

for {

126

samples <- TestConfig.samples

127

size <- TestConfig.size

128

} yield assertTrue(samples > 0 && size > 0)

129

}

130

```

131

132

### TestEnvironment

133

134

Combined environment type containing all standard test services.

135

136

```scala { .api }

137

/**

138

* Standard test environment combining all test services

139

*/

140

type TestEnvironment = Annotations with Live with Sized with TestConfig

141

142

object TestEnvironment {

143

/**

144

* Create test environment from live system services

145

* @return layer providing complete test environment

146

*/

147

val live: ZLayer[Clock with Console with System with Random, Nothing, TestEnvironment]

148

149

/**

150

* Access any service from test environment

151

* @return layer that provides access to the environment

152

*/

153

val any: ZLayer[TestEnvironment, Nothing, TestEnvironment]

154

}

155

156

/**

157

* Layer providing live system services for test environment creation

158

*/

159

val liveEnvironment: Layer[Nothing, Clock with Console with System with Random]

160

161

/**

162

* Complete test environment layer (recommended for most tests)

163

*/

164

val testEnvironment: ZLayer[Any, Nothing, TestEnvironment]

165

```

166

167

**Usage Examples:**

168

169

```scala

170

import zio.test._

171

import zio._

172

173

// Using default test environment

174

object MyTestSpec extends ZIOSpecDefault {

175

def spec = suite("My Tests")(

176

test("basic test") {

177

// Has access to full TestEnvironment

178

for {

179

time <- Clock.currentTime(TimeUnit.MILLISECONDS)

180

_ <- Console.printLine(s"Current time: $time")

181

random <- Random.nextInt(100)

182

} yield assertTrue(time > 0 && random >= 0 && random < 100)

183

}

184

)

185

}

186

187

// Custom environment combination

188

val customTestEnv: ZLayer[Any, Nothing, TestEnvironment] =

189

ZLayer.make[TestEnvironment](

190

TestClock.default,

191

TestConsole.debug,

192

TestRandom.deterministic(12345L),

193

TestSystem.default,

194

Annotations.live,

195

Live.default,

196

Sized.live(50),

197

TestConfig.live(1, 0, 500, 1000, 50)

198

)

199

200

object CustomEnvSpec extends ZIOSpec[TestEnvironment] {

201

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

202

test("uses custom environment") {

203

for {

204

size <- Sized.size

205

samples <- TestConfig.samples

206

} yield assertTrue(size == 50 && samples == 500)

207

}

208

).provideLayer(customTestEnv)

209

}

210

```

211

212

### TestArgs

213

214

Command-line argument parsing for test runners.

215

216

```scala { .api }

217

/**

218

* Command-line arguments for test execution

219

*/

220

case class TestArgs(

221

testSearchTerms: List[String] = Nil,

222

tagSearchTerms: List[String] = Nil,

223

testTaskPolicy: TestTaskPolicy = TestTaskPolicy.Sequential,

224

225

// Execution parameters

226

repeats: Option[Int] = None,

227

retries: Option[Int] = None,

228

samples: Option[Int] = None,

229

shrinks: Option[Int] = None,

230

size: Option[Int] = None,

231

232

// Output control

233

verbose: Boolean = false,

234

color: Boolean = true,

235

summary: Boolean = true

236

)

237

238

object TestArgs {

239

/**

240

* Parse command-line arguments

241

* @param args command-line argument list

242

* @return parsed test arguments

243

*/

244

def parse(args: List[String]): Either[String, TestArgs]

245

246

/**

247

* Parse command-line arguments with defaults

248

* @param args command-line argument list

249

* @param defaults default test arguments

250

* @return parsed test arguments

251

*/

252

def parse(args: List[String], defaults: TestArgs): Either[String, TestArgs]

253

254

/**

255

* Empty test arguments (all defaults)

256

*/

257

val empty: TestArgs

258

}

259

260

/**

261

* Test execution policy

262

*/

263

sealed trait TestTaskPolicy

264

object TestTaskPolicy {

265

case object Sequential extends TestTaskPolicy

266

case object Parallel extends TestTaskPolicy

267

case class ParallelN(n: Int) extends TestTaskPolicy

268

}

269

```

270

271

**Usage Examples:**

272

273

```scala

274

import zio.test._

275

276

// Parsing command-line arguments

277

val args = List("--samples", "1000", "--parallel", "--verbose", "UserTests")

278

val testArgs = TestArgs.parse(args) match {

279

case Right(args) => args

280

case Left(error) => throw new IllegalArgumentException(error)

281

}

282

283

// Using parsed arguments to configure tests

284

val configFromArgs = testArgs.samples.fold(TestConfig.default) { samples =>

285

TestConfig.live(

286

repeats = testArgs.repeats.getOrElse(1),

287

retries = testArgs.retries.getOrElse(0),

288

samples = samples,

289

shrinks = testArgs.shrinks.getOrElse(1000),

290

size = testArgs.size.getOrElse(100)

291

)

292

}

293

```

294

295

### Annotations

296

297

Service for attaching metadata to tests.

298

299

```scala { .api }

300

/**

301

* Service for managing test annotations and metadata

302

*/

303

trait Annotations {

304

/**

305

* Get annotation value by key

306

* @param key annotation key

307

* @return effect producing optional annotation value

308

*/

309

def get[V](key: TestAnnotation[V]): UIO[V]

310

311

/**

312

* Annotate with key-value pair

313

* @param key annotation key

314

* @param value annotation value

315

* @return effect that adds the annotation

316

*/

317

def annotate[V](key: TestAnnotation[V], value: V): UIO[Unit]

318

319

/**

320

* Get all current annotations

321

* @return effect producing annotation map

322

*/

323

def annotationMap: UIO[TestAnnotationMap]

324

325

/**

326

* Supervise effect with annotation inheritance

327

* @param zio effect to supervise

328

* @return supervised effect with annotations

329

*/

330

def supervisedFibers[R, E, A](zio: ZIO[R, E, A]): ZIO[R, E, A]

331

}

332

333

object Annotations {

334

/**

335

* Live annotations implementation

336

*/

337

val live: ULayer[Annotations]

338

}

339

340

/**

341

* Test annotation key-value pair

342

*/

343

trait TestAnnotation[V] {

344

/**

345

* Annotation identifier

346

*/

347

def identifier: String

348

349

/**

350

* Initial/default value

351

*/

352

def initial: V

353

354

/**

355

* Combine two annotation values

356

* @param v1 first value

357

* @param v2 second value

358

* @return combined value

359

*/

360

def combine(v1: V, v2: V): V

361

}

362

363

object TestAnnotation {

364

/**

365

* Create custom annotation

366

* @param name annotation name

367

* @param initialValue initial value

368

* @param combineFunction value combination function

369

* @return annotation instance

370

*/

371

def apply[V](

372

name: String,

373

initialValue: V,

374

combineFunction: (V, V) => V

375

): TestAnnotation[V]

376

377

// Built-in annotations

378

val ignored: TestAnnotation[Boolean]

379

val repeated: TestAnnotation[Int]

380

val retried: TestAnnotation[Int]

381

val tagged: TestAnnotation[Set[String]]

382

val timing: TestAnnotation[Duration]

383

}

384

```

385

386

**Usage Examples:**

387

388

```scala

389

import zio.test._

390

import zio._

391

392

// Using built-in annotations

393

test("annotated test") {

394

for {

395

_ <- Annotations.annotate(TestAnnotation.tagged, Set("slow", "integration"))

396

_ <- Annotations.annotate(TestAnnotation.repeated, 5)

397

annotations <- Annotations.annotationMap

398

} yield assertTrue(annotations.get(TestAnnotation.tagged).contains("slow"))

399

}

400

401

// Custom annotations

402

val databaseAnnotation = TestAnnotation[String](

403

"database",

404

"none",

405

(_, newer) => newer // Use newer value

406

)

407

408

test("database test") {

409

for {

410

_ <- Annotations.annotate(databaseAnnotation, "postgresql")

411

dbType <- Annotations.get(databaseAnnotation)

412

} yield assertTrue(dbType == "postgresql")

413

}

414

```

415

416

### Live Service

417

418

Service for executing effects with live (production) implementations.

419

420

```scala { .api }

421

/**

422

* Service for accessing live implementations of system services

423

*/

424

trait Live {

425

/**

426

* Execute effect with live service implementations

427

* @param zio effect to execute with live services

428

* @return effect executed with live services

429

*/

430

def provide[R, E, A](zio: ZIO[R, E, A]): ZIO[R, E, A]

431

}

432

433

object Live {

434

/**

435

* Default live service implementation

436

*/

437

val default: ULayer[Live]

438

439

/**

440

* Execute effect with live services (convenience function)

441

* @param zio effect to execute

442

* @return effect with live services

443

*/

444

def live[R, E, A](zio: ZIO[R, E, A]): ZIO[R with Live, E, A]

445

446

/**

447

* Transform effect to use live services for outer effect while preserving

448

* test environment for inner effect

449

* @param zio inner effect using test environment

450

* @param f transformation using live environment

451

* @return transformed effect

452

*/

453

def withLive[R, E, E1, A, B](zio: ZIO[R, E, A])(

454

f: ZIO[R, E, A] => ZIO[R, E1, B]

455

): ZIO[R with Live, E1, B]

456

}

457

```

458

459

**Usage Examples:**

460

461

```scala

462

import zio.test._

463

import zio._

464

465

// Execute with live services when needed

466

test("performance test with real time") {

467

for {

468

// Use test clock for setup

469

testClock <- ZIO.service[TestClock]

470

_ <- testClock.setTime(Duration.zero)

471

472

// Use live clock for actual measurement

473

result <- Live.live(

474

for {

475

start <- Clock.currentTime(TimeUnit.MILLISECONDS)

476

_ <- ZIO.sleep(100.millis) // Actually sleep

477

end <- Clock.currentTime(TimeUnit.MILLISECONDS)

478

} yield end - start

479

)

480

} yield assertTrue(result >= 100L) // Real time elapsed

481

}

482

483

// Mix test and live environments

484

test("hybrid test environment") {

485

Live.withLive(

486

// This runs with test environment

487

for {

488

_ <- Console.printLine("Test output") // Goes to test console

489

value <- Random.nextInt(100) // Uses test random

490

} yield value

491

) { effect =>

492

// This transformation uses live environment

493

for {

494

_ <- Console.printLine("Live output") // Goes to real console

495

result <- effect // Execute inner effect with test env

496

} yield result

497

}

498

}

499

```

500

501

### Environment Manipulation

502

503

Functions for working with and modifying test environments.

504

505

```scala { .api }

506

/**

507

* Execute with modified annotations

508

* @param annotations new annotations service

509

* @param zio effect to execute

510

* @return effect with modified annotations

511

*/

512

def withAnnotations[R, E, A <: Annotations, B](annotations: => A)(

513

zio: => ZIO[R, E, B]

514

): ZIO[R, E, B]

515

516

/**

517

* Execute with modified test configuration

518

* @param testConfig new test configuration

519

* @param zio effect to execute

520

* @return effect with modified configuration

521

*/

522

def withTestConfig[R, E, A <: TestConfig, B](testConfig: => A)(

523

zio: => ZIO[R, E, B]

524

): ZIO[R, E, B]

525

526

/**

527

* Execute with modified size configuration

528

* @param sized new sized service

529

* @param zio effect to execute

530

* @return effect with modified size

531

*/

532

def withSized[R, E, A <: Sized, B](sized: => A)(

533

zio: => ZIO[R, E, B]

534

): ZIO[R, E, B]

535

536

/**

537

* Execute with modified live service

538

* @param live new live service

539

* @param zio effect to execute

540

* @return effect with modified live service

541

*/

542

def withLive[R, E, A <: Live, B](live: => A)(

543

zio: => ZIO[R, E, B]

544

): ZIO[R, E, B]

545

```

546

547

**Usage Examples:**

548

549

```scala

550

import zio.test._

551

import zio._

552

553

// Temporarily modify test configuration

554

test("high sample count test") {

555

withTestConfig(TestConfig.live(1, 0, 10000, 5000, 200)) {

556

check(Gen.listOf(Gen.anyInt)) { list =>

557

assertTrue(list.reverse.reverse == list)

558

}

559

}

560

}

561

562

// Temporarily modify generator size

563

test("large data structures") {

564

withSized(Sized(1000)) {

565

check(Gen.listOf(Gen.anyString)) { largeList =>

566

assertTrue(largeList.size <= 1000)

567

}

568

}

569

}

570

571

// Environment scoped modifications

572

test("scoped environment changes") {

573

for {

574

// Normal size

575

normalList <- Gen.listOf(Gen.anyInt).sample.runHead

576

_ <- ZIO.scoped {

577

withSizedScoped(Sized(10)) {

578

// Large size in this scope

579

Gen.listOf(Gen.anyInt).sample.runHead.map { largeList =>

580

// Compare sizes

581

assertTrue(largeList.exists(_.size > normalList.map(_.size).getOrElse(0)))

582

}

583

}

584

}

585

} yield assertTrue(true)

586

}

587

```