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-environment.mddocs/

0

# Test Environment

1

2

Controllable test services that replace ZIO's standard environment for deterministic testing.

3

4

## Capabilities

5

6

### TestClock

7

8

Controllable clock service for testing time-dependent operations.

9

10

```scala { .api }

11

/**

12

* Test clock service that provides deterministic time control

13

*/

14

trait TestClock extends Clock {

15

/** Advances the clock by specified duration */

16

def adjust(duration: Duration): UIO[Unit]

17

18

/** Sets clock to specific date and time */

19

def setDateTime(dateTime: OffsetDateTime): UIO[Unit]

20

21

/** Sets clock to specific time offset */

22

def setTime(duration: Duration): UIO[Unit]

23

24

/** Sets time zone for the clock */

25

def setTimeZone(zone: ZoneId): UIO[Unit]

26

27

/** Gets list of pending sleep operations */

28

def sleeps: UIO[List[Duration]]

29

30

/** Gets current time zone */

31

def timeZone: UIO[ZoneId]

32

}

33

34

object TestClock {

35

/** Access TestClock service from environment */

36

def adjust(duration: Duration): URIO[TestClock, Unit]

37

def setDateTime(dateTime: OffsetDateTime): URIO[TestClock, Unit]

38

def setTime(duration: Duration): URIO[TestClock, Unit]

39

def sleeps: URIO[TestClock, List[Duration]]

40

}

41

```

42

43

**Usage Examples:**

44

45

```scala

46

import zio.test.environment.TestClock

47

import zio.duration._

48

49

testM("time-based operation") {

50

for {

51

fiber <- someTTimedOperation.fork

52

_ <- TestClock.adjust(1.hour)

53

result <- fiber.join

54

} yield assert(result)(isSuccess)

55

}

56

57

testM("timeout behavior") {

58

for {

59

_ <- TestClock.setTime(0.seconds)

60

fiber <- longRunningTask.timeout(30.seconds).fork

61

_ <- TestClock.adjust(31.seconds)

62

result <- fiber.join

63

} yield assert(result)(isNone)

64

}

65

```

66

67

### TestConsole

68

69

Controllable console service for testing input/output operations.

70

71

```scala { .api }

72

/**

73

* Test console service that captures output and provides input

74

*/

75

trait TestConsole extends Console {

76

/** Clears the input buffer */

77

def clearInput: UIO[Unit]

78

79

/** Clears the output buffer */

80

def clearOutput: UIO[Unit]

81

82

/** Clears the error output buffer */

83

def clearOutputErr: UIO[Unit]

84

85

/** Adds input lines to be read */

86

def feedLines(lines: String*): UIO[Unit]

87

88

/** Gets all output lines written */

89

def output: UIO[Vector[String]]

90

91

/** Gets all error output lines written */

92

def outputErr: UIO[Vector[String]]

93

}

94

95

object TestConsole {

96

/** Access TestConsole service from environment */

97

def clearInput: URIO[TestConsole, Unit]

98

def clearOutput: URIO[TestConsole, Unit]

99

def feedLines(lines: String*): URIO[TestConsole, Unit]

100

def output: URIO[TestConsole, Vector[String]]

101

def outputErr: URIO[TestConsole, Vector[String]]

102

}

103

```

104

105

**Usage Examples:**

106

107

```scala

108

import zio.test.environment.TestConsole

109

import zio.console._

110

111

testM("console interaction") {

112

for {

113

_ <- TestConsole.feedLines("user input", "more input")

114

_ <- myInteractiveProgram

115

output <- TestConsole.output

116

} yield assert(output)(contains("Welcome!"))

117

}

118

119

testM("error output") {

120

for {

121

_ <- programThatPrintsErrors

122

errs <- TestConsole.outputErr

123

} yield assert(errs)(isNonEmpty)

124

}

125

```

126

127

### TestRandom

128

129

Controllable random service for deterministic testing.

130

131

```scala { .api }

132

/**

133

* Test random service that provides controllable randomness

134

*/

135

trait TestRandom extends Random {

136

/** Clears boolean values buffer */

137

def clearBooleans: UIO[Unit]

138

139

/** Clears byte array buffer */

140

def clearBytes: UIO[Unit]

141

142

/** Clears character values buffer */

143

def clearChars: UIO[Unit]

144

145

/** Clears double values buffer */

146

def clearDoubles: UIO[Unit]

147

148

/** Clears float values buffer */

149

def clearFloats: UIO[Unit]

150

151

/** Clears integer values buffer */

152

def clearInts: UIO[Unit]

153

154

/** Clears long values buffer */

155

def clearLongs: UIO[Unit]

156

157

/** Clears string values buffer */

158

def clearStrings: UIO[Unit]

159

160

/** Adds boolean values to be returned */

161

def feedBooleans(booleans: Boolean*): UIO[Unit]

162

163

/** Adds byte arrays to be returned */

164

def feedBytes(bytes: Chunk[Byte]*): UIO[Unit]

165

166

/** Adds character values to be returned */

167

def feedChars(chars: Char*): UIO[Unit]

168

169

/** Adds double values to be returned */

170

def feedDoubles(doubles: Double*): UIO[Unit]

171

172

/** Adds float values to be returned */

173

def feedFloats(floats: Float*): UIO[Unit]

174

175

/** Adds integer values to be returned */

176

def feedInts(ints: Int*): UIO[Unit]

177

178

/** Adds long values to be returned */

179

def feedLongs(longs: Long*): UIO[Unit]

180

181

/** Adds string values to be returned */

182

def feedStrings(strings: String*): UIO[Unit]

183

184

/** Sets the random seed */

185

def setSeed(seed: Long): UIO[Unit]

186

}

187

188

object TestRandom {

189

/** Access TestRandom service from environment */

190

def feedInts(ints: Int*): URIO[TestRandom, Unit]

191

def feedDoubles(doubles: Double*): URIO[TestRandom, Unit]

192

def feedBooleans(booleans: Boolean*): URIO[TestRandom, Unit]

193

def setSeed(seed: Long): URIO[TestRandom, Unit]

194

}

195

```

196

197

**Usage Examples:**

198

199

```scala

200

import zio.test.environment.TestRandom

201

import zio.random._

202

203

testM("deterministic randomness") {

204

for {

205

_ <- TestRandom.feedInts(1, 2, 3, 4, 5)

206

result <- randomGameSimulation

207

} yield assert(result.winner)(equalTo("Player1"))

208

}

209

210

testM("seeded randomness") {

211

for {

212

_ <- TestRandom.setSeed(12345L)

213

result1 <- randomOperation

214

_ <- TestRandom.setSeed(12345L)

215

result2 <- randomOperation

216

} yield assert(result1)(equalTo(result2))

217

}

218

```

219

220

### TestSystem

221

222

Controllable system service for testing environment variables and system properties.

223

224

```scala { .api }

225

/**

226

* Test system service that provides controllable system state

227

*/

228

trait TestSystem extends System {

229

/** Clears all environment variables */

230

def clearEnv: UIO[Unit]

231

232

/** Clears all system properties */

233

def clearProperties: UIO[Unit]

234

235

/** Sets environment variable */

236

def putEnv(name: String, value: String): UIO[Unit]

237

238

/** Sets system property */

239

def putProperty(name: String, value: String): UIO[Unit]

240

241

/** Sets line separator */

242

def setLineSeparator(lineSeparator: String): UIO[Unit]

243

}

244

245

object TestSystem {

246

/** Access TestSystem service from environment */

247

def clearEnv: URIO[TestSystem, Unit]

248

def putEnv(name: String, value: String): URIO[TestSystem, Unit]

249

def putProperty(name: String, value: String): URIO[TestSystem, Unit]

250

}

251

```

252

253

**Usage Examples:**

254

255

```scala

256

import zio.test.environment.TestSystem

257

import zio.system._

258

259

testM("environment variables") {

260

for {

261

_ <- TestSystem.putEnv("TEST_MODE", "enabled")

262

_ <- TestSystem.putEnv("API_KEY", "test-key-123")

263

result <- programThatReadsEnvVars

264

} yield assert(result)(isSuccess)

265

}

266

267

testM("system properties") {

268

for {

269

_ <- TestSystem.putProperty("user.name", "testuser")

270

result <- programThatReadsSystemProps

271

} yield assert(result.username)(equalTo("testuser"))

272

}

273

```

274

275

### TestEnvironment

276

277

Complete test environment combining all test services.

278

279

```scala { .api }

280

/**

281

* Complete test environment with all controllable services

282

*/

283

type TestEnvironment = TestClock with TestConsole with TestRandom with TestSystem

284

285

/**

286

* Complete ZIO test environment

287

*/

288

type ZTestEnv = TestClock with TestConsole with TestRandom with TestSystem

289

290

object TestEnvironment {

291

/** Live layer providing test environment */

292

val live: Layer[Nothing, TestEnvironment]

293

}

294

295

/** Default test environment layer */

296

val testEnvironment: Layer[Nothing, TestEnvironment]

297

298

/** Managed test environment resource */

299

val testEnvironmentManaged: TaskManaged[TestEnvironment]

300

```

301

302

### Environment Services Access

303

304

Service objects for accessing test environment components.

305

306

```scala { .api }

307

object Annotations {

308

trait Service {

309

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

310

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

311

def supervisedFibers: UIO[SortedSet[Fiber.Runtime[Any, Any]]]

312

}

313

314

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

315

def get[V](key: TestAnnotation[V]): URIO[Annotations, V]

316

val live: Layer[Nothing, Annotations]

317

}

318

319

object Sized {

320

trait Service {

321

def size: UIO[Int]

322

def withSize[R, E, A](size: Int)(zio: ZIO[R, E, A]): ZIO[R, E, A]

323

}

324

325

def live(size: Int): Layer[Nothing, Sized]

326

def size: URIO[Sized, Int]

327

def withSize[R <: Sized, E, A](size: Int)(zio: ZIO[R, E, A]): ZIO[R, E, A]

328

}

329

330

object TestConfig {

331

trait Service {

332

def repeats: Int

333

def retries: Int

334

def samples: Int

335

def shrinks: Int

336

}

337

338

def live(repeats: Int, retries: Int, samples: Int, shrinks: Int): ZLayer[Any, Nothing, TestConfig]

339

val repeats: URIO[TestConfig, Int]

340

val retries: URIO[TestConfig, Int]

341

val samples: URIO[TestConfig, Int]

342

val shrinks: URIO[TestConfig, Int]

343

}

344

```

345

346

## Complete Example

347

348

```scala

349

import zio.test._

350

import zio.test.environment._

351

import zio.duration._

352

353

object TestEnvironmentExample extends DefaultRunnableSpec {

354

def spec = suite("Test Environment Example")(

355

356

testM("clock control") {

357

for {

358

start <- clock.nanoTime

359

_ <- TestClock.setTime(1.hour)

360

end <- clock.nanoTime

361

diff = end - start

362

} yield assert(diff)(isGreaterThan(3600000000000L)) // 1 hour in nanos

363

},

364

365

testM("console interaction") {

366

for {

367

_ <- TestConsole.feedLines("Alice", "25")

368

_ <- putStrLn("Enter name:")

369

name <- getStrLn

370

_ <- putStrLn("Enter age:")

371

age <- getStrLn

372

output <- TestConsole.output

373

} yield assert(output)(contains("Enter name:")) &&

374

assert(name)(equalTo("Alice")) &&

375

assert(age)(equalTo("25"))

376

},

377

378

testM("deterministic random") {

379

for {

380

_ <- TestRandom.feedInts(42, 17, 99)

381

int1 <- nextInt

382

int2 <- nextInt

383

int3 <- nextInt

384

} yield assert(int1)(equalTo(42)) &&

385

assert(int2)(equalTo(17)) &&

386

assert(int3)(equalTo(99))

387

},

388

389

testM("system environment") {

390

for {

391

_ <- TestSystem.putEnv("HOME", "/test/home")

392

_ <- TestSystem.putProperty("user.name", "testuser")

393

home <- system.env("HOME")

394

user <- system.property("user.name")

395

} yield assert(home)(isSome(equalTo("/test/home"))) &&

396

assert(user)(isSome(equalTo("testuser")))

397

}

398

)

399

}

400

```