or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

actor-refs.mdconfiguration.mdcore-testing.mddispatchers.mdevent-filtering.mdindex.mdjava-dsl.mdpackage-functions.mdsynchronization.mdtest-actors.mdutilities.md

package-functions.mddocs/

0

# Package-Level Functions

1

2

Global utility functions and implicit classes available at the package level for common testing operations and time dilation.

3

4

## Capabilities

5

6

### Event Filtering Functions

7

8

Package-level functions for convenient event filtering operations.

9

10

```scala { .api }

11

package object testkit {

12

// Event filtering with multiple filters

13

def filterEvents[T](eventFilters: Iterable[EventFilter])(block: => T)(implicit system: ActorSystem): T

14

def filterEvents[T](eventFilters: EventFilter*)(block: => T)(implicit system: ActorSystem): T

15

16

// Exception filtering shorthand

17

def filterException[T <: Throwable](block: => Unit)(implicit system: ActorSystem, t: ClassTag[T]): Unit

18

}

19

```

20

21

**Usage Examples:**

22

23

```scala

24

import akka.testkit._

25

26

class PackageFunctionsTest extends TestKit(ActorSystem("TestSystem")) {

27

"Package-level filterEvents" should {

28

"filter multiple event types" in {

29

filterEvents(

30

EventFilter.error(occurrences = 1),

31

EventFilter.warning(pattern = "deprecated".r, occurrences = 2),

32

EventFilter[RuntimeException](occurrences = 1)

33

) {

34

val actor = system.actorOf(Props(new Actor {

35

def receive = {

36

case "error" => log.error("Test error")

37

case "warn" =>

38

log.warning("Use of deprecated feature")

39

log.warning("Another deprecated warning")

40

case "exception" => throw new RuntimeException("Test exception")

41

}

42

}))

43

44

actor ! "error"

45

actor ! "warn"

46

actor ! "exception"

47

}

48

}

49

50

"work with iterable filters" in {

51

val filters = List(

52

EventFilter.info(message = "Starting", occurrences = 1),

53

EventFilter.info(message = "Completed", occurrences = 1)

54

)

55

56

filterEvents(filters) {

57

val actor = system.actorOf(Props(new Actor {

58

def receive = {

59

case "process" =>

60

log.info("Starting")

61

// Do work

62

log.info("Completed")

63

}

64

}))

65

66

actor ! "process"

67

}

68

}

69

}

70

71

"Package-level filterException" should {

72

"provide shorthand for exception filtering" in {

73

filterException[IllegalArgumentException] {

74

val actor = system.actorOf(Props(new Actor {

75

def receive = {

76

case invalid: String if invalid.isEmpty =>

77

throw new IllegalArgumentException("Empty string not allowed")

78

}

79

}))

80

81

actor ! ""

82

}

83

}

84

85

"work with type inference" in {

86

import scala.reflect.ClassTag

87

88

def testException[E <: Throwable : ClassTag](triggerException: => Unit): Unit = {

89

filterException[E] {

90

triggerException

91

}

92

}

93

94

testException[NullPointerException] {

95

throw new NullPointerException("Test NPE")

96

}

97

}

98

}

99

}

100

```

101

102

### Time Dilation Implicit Class

103

104

Implicit class for scaling durations based on test environment.

105

106

```scala { .api }

107

implicit class TestDuration(val duration: FiniteDuration) extends AnyVal {

108

def dilated(implicit system: ActorSystem): FiniteDuration

109

}

110

```

111

112

**Usage Examples:**

113

114

```scala

115

import akka.testkit._

116

import scala.concurrent.duration._

117

118

class TimeDilationTest extends TestKit(ActorSystem("TestSystem")) {

119

"TestDuration implicit class" should {

120

"dilate durations for test reliability" in {

121

val originalTimeout = 1.second

122

val dilatedTimeout = originalTimeout.dilated

123

124

// Dilated timeout accounts for slow test environments

125

dilatedTimeout should be >= originalTimeout

126

127

// Use in expectations

128

within(5.seconds.dilated) {

129

// Code that might run slowly in CI

130

Thread.sleep(100)

131

expectNoMessage(500.millis.dilated)

132

}

133

}

134

135

"work with various duration types" in {

136

// All duration types work

137

val millis = 100.millis.dilated

138

val seconds = 2.seconds.dilated

139

val minutes = 1.minute.dilated

140

141

millis should be >= 100.millis

142

seconds should be >= 2.seconds

143

minutes should be >= 1.minute

144

}

145

146

"respect test time factor configuration" in {

147

// Time factor configured in application.conf: akka.test.timefactor = 2.0

148

val original = 1.second

149

val dilated = original.dilated

150

151

// With timefactor = 2.0, dilated should be ~2x original

152

val settings = TestKitExtension(system)

153

val expectedDilated = Duration.fromNanos((original.toNanos * settings.TestTimeFactor).toLong)

154

155

dilated should be(expectedDilated)

156

}

157

158

"be used in actor timing tests" in {

159

class TimedActor extends Actor {

160

import context.dispatcher

161

162

def receive = {

163

case "delayed-response" =>

164

val originalSender = sender()

165

context.system.scheduler.scheduleOnce(200.millis.dilated) {

166

originalSender ! "response"

167

}

168

}

169

}

170

171

val actor = system.actorOf(Props[TimedActor]())

172

actor ! "delayed-response"

173

174

// Wait with dilated timeout to account for test environment

175

expectMsg(1.second.dilated, "response")

176

}

177

}

178

}

179

```

180

181

### Integration with TestKit Methods

182

183

Package-level functions integrate seamlessly with TestKit methods:

184

185

```scala

186

class IntegrationTest extends TestKit(ActorSystem("TestSystem")) with ImplicitSender {

187

"Package functions with TestKit" should {

188

"combine with expectation methods" in {

189

val actor = system.actorOf(Props(new Actor {

190

def receive = {

191

case "test" =>

192

log.info("Processing test message")

193

sender() ! "processed"

194

}

195

}))

196

197

filterEvents(EventFilter.info(message = "Processing test message")) {

198

actor ! "test"

199

expectMsg(3.seconds.dilated, "processed")

200

}

201

}

202

203

"work with awaitCond" in {

204

@volatile var completed = false

205

206

val actor = system.actorOf(Props(new Actor {

207

def receive = {

208

case "complete" =>

209

Thread.sleep(100) // Simulate work

210

completed = true

211

}

212

}))

213

214

actor ! "complete"

215

awaitCond(completed, max = 2.seconds.dilated)

216

217

assert(completed)

218

}

219

220

"combine with within blocks" in {

221

within(1.second.dilated) {

222

filterEvents(EventFilter.debug(start = "Debug message")) {

223

val actor = system.actorOf(Props(new Actor {

224

def receive = {

225

case msg =>

226

log.debug(s"Debug message: $msg")

227

sender() ! s"handled: $msg"

228

}

229

}))

230

231

actor ! "test"

232

expectMsg("handled: test")

233

}

234

}

235

}

236

}

237

}

238

```

239

240

### Advanced Usage Patterns

241

242

**Nested Event Filtering:**

243

244

```scala

245

class NestedFilteringTest extends TestKit(ActorSystem("TestSystem")) {

246

"Nested event filtering" should {

247

"work with multiple layers" in {

248

filterEvents(EventFilter.error(occurrences = 1)) {

249

filterEvents(EventFilter.warning(occurrences = 2)) {

250

val actor = system.actorOf(Props(new Actor {

251

def receive = {

252

case "process" =>

253

log.warning("First warning")

254

log.warning("Second warning")

255

log.error("An error occurred")

256

}

257

}))

258

259

actor ! "process"

260

}

261

}

262

}

263

}

264

}

265

```

266

267

**Dynamic Filter Creation:**

268

269

```scala

270

class DynamicFilterTest extends TestKit(ActorSystem("TestSystem")) {

271

"Dynamic filter creation" should {

272

"create filters based on test parameters" in {

273

def testWithFilters(errorCount: Int, warningCount: Int): Unit = {

274

val filters = Seq(

275

if (errorCount > 0) Some(EventFilter.error(occurrences = errorCount)) else None,

276

if (warningCount > 0) Some(EventFilter.warning(occurrences = warningCount)) else None

277

).flatten

278

279

filterEvents(filters) {

280

val actor = system.actorOf(Props(new Actor {

281

def receive = {

282

case (errors: Int, warnings: Int) =>

283

(1 to errors).foreach(_ => log.error("Error"))

284

(1 to warnings).foreach(_ => log.warning("Warning"))

285

}

286

}))

287

288

actor ! (errorCount, warningCount)

289

}

290

}

291

292

testWithFilters(2, 3)

293

testWithFilters(0, 1)

294

testWithFilters(1, 0)

295

}

296

}

297

}

298

```

299

300

### Configuration and Environment

301

302

Package functions respect TestKit configuration:

303

304

```hocon

305

# application.conf

306

akka {

307

test {

308

# Time dilation factor - all dilated durations multiplied by this

309

timefactor = 1.0

310

311

# Event filter leeway - extra time to wait for expected log events

312

filter-leeway = 3s

313

314

# Default timeouts

315

single-expect-default = 3s

316

multi-expect-default = 3s

317

}

318

}

319

```

320

321

**Accessing Configuration:**

322

323

```scala

324

class ConfigurationAccessTest extends TestKit(ActorSystem("TestSystem")) {

325

"Configuration access" should {

326

"use configured time factors" in {

327

val settings = TestKitExtension(system)

328

val timeFactor = settings.TestTimeFactor

329

330

val original = 1.second

331

val dilated = original.dilated

332

val expected = Duration.fromNanos((original.toNanos * timeFactor).toLong)

333

334

dilated should be(expected)

335

}

336

}

337

}

338

```

339

340

### Best Practices

341

342

1. **Always Use Dilated Timeouts**: Use `.dilated` for all test timeouts to handle slow environments

343

2. **Specific Event Filtering**: Be specific with event filters to avoid false positives

344

3. **Combine Functions**: Mix package functions with TestKit methods for comprehensive testing

345

4. **Environment Awareness**: Configure appropriate time factors for different test environments

346

347

```scala

348

// Good: Dilated timeouts for reliability

349

expectMsg(5.seconds.dilated, expectedMessage)

350

awaitCond(condition, max = 3.seconds.dilated)

351

352

// Good: Specific event filtering

353

filterEvents(

354

EventFilter.error(source = "com.myapp.Service", occurrences = 1),

355

EventFilter.warning(pattern = "deprecated.*method".r, occurrences = 1)

356

) {

357

// test code

358

}

359

360

// Good: Combined with TestKit methods

361

within(10.seconds.dilated) {

362

filterException[IllegalStateException] {

363

actor ! InvalidCommand()

364

}

365

}

366

```