or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdcore-testing.mdindex.mdproperty-testing.mdsmart-assertions.mdtest-aspects.mdtest-services.md

smart-assertions.mddocs/

0

# Smart Assertions (Scala 3)

1

2

Compile-time smart assertions with automatic expression analysis and enhanced error reporting. Smart assertions provide more intuitive test writing with better error messages by analyzing expressions at compile time.

3

4

## Capabilities

5

6

### Smart Assert

7

8

The primary smart assertion function that analyzes boolean expressions at compile time.

9

10

```scala { .api }

11

/**

12

* Smart assertion with compile-time expression analysis

13

* @param assertion - Boolean expression to test (analyzed at compile time)

14

* @return TestResult with detailed error reporting

15

*/

16

inline def assertTrue(inline assertion: Boolean)(implicit

17

trace: Trace,

18

sourceLocation: SourceLocation

19

): TestResult

20

```

21

22

**Usage Examples:**

23

24

```scala

25

import zio.test._

26

27

test("smart assertions") {

28

val user = User("Alice", 25, active = true)

29

val numbers = List(1, 2, 3, 4, 5)

30

31

// Simple comparisons with enhanced error messages

32

assertTrue(user.age >= 18)

33

assertTrue(user.name.nonEmpty)

34

assertTrue(user.active)

35

36

// Complex expressions are analyzed

37

assertTrue(numbers.size == 5 && numbers.contains(3))

38

assertTrue(user.age > 20 && user.name.startsWith("A"))

39

40

// Method calls are captured

41

assertTrue(numbers.head == 1)

42

assertTrue(numbers.last == 5)

43

assertTrue(user.name.length > 2)

44

}

45

```

46

47

### Smart Assert with Explicit Assertion

48

49

Smart assertion that applies a traditional assertion to a value with compile-time expression capture.

50

51

```scala { .api }

52

/**

53

* Smart assertion for single values with traditional assertions

54

* @param value - Value to test (expression captured at compile time)

55

* @param assertion - Assertion to apply to the value

56

* @return TestResult with enhanced error reporting

57

*/

58

inline def assert[A](inline value: A)(inline assertion: Assertion[A])(implicit

59

trace: Trace,

60

sourceLocation: SourceLocation

61

): TestResult

62

```

63

64

**Usage Examples:**

65

66

```scala

67

import zio.test._

68

import zio.test.Assertion._

69

70

test("smart assert with explicit assertions") {

71

val numbers = List(1, 2, 3, 4, 5)

72

val name = "Alice"

73

val age = 25

74

75

// Explicit assertions with smart error reporting

76

assert(numbers)(hasSize(equalTo(5)))

77

assert(numbers)(contains(3))

78

assert(numbers)(forall(isGreaterThan(0)))

79

80

assert(name)(hasLength(equalTo(5)))

81

assert(name)(startsWith("A"))

82

83

assert(age)(isGreaterThanEqualTo(18))

84

assert(age)(isLessThan(100))

85

}

86

```

87

88

### Smart Assert ZIO

89

90

Smart assertion for effectful computations with compile-time expression analysis.

91

92

```scala { .api }

93

/**

94

* Smart assertion for effectful values

95

* @param effect - ZIO effect producing value to test

96

* @param assertion - Assertion to apply to the effect result

97

* @return ZIO effect producing TestResult

98

*/

99

inline def assertZIO[R, E, A](effect: ZIO[R, E, A])(inline assertion: Assertion[A])(implicit

100

trace: Trace,

101

sourceLocation: SourceLocation

102

): ZIO[R, E, TestResult]

103

```

104

105

**Usage Examples:**

106

107

```scala

108

import zio.test._

109

import zio.test.Assertion._

110

111

test("smart assertZIO") {

112

// Testing effectful computations

113

assertZIO(ZIO.succeed(42))(equalTo(42)) *>

114

assertZIO(ZIO.succeed("hello"))(hasLength(equalTo(5))) *>

115

assertZIO(ZIO.succeed(List(1, 2, 3)))(hasSize(equalTo(3)))

116

}

117

118

test("assertZIO with service calls") {

119

for {

120

// Testing service method results

121

result1 <- assertZIO(userService.findById(1))(isSome(anything))

122

result2 <- assertZIO(userService.count())(isGreaterThan(0))

123

result3 <- assertZIO(mathService.add(2, 3))(equalTo(5))

124

} yield result1 && result2 && result3

125

}

126

```

127

128

### Type Checking (Compile-time)

129

130

Compile-time type checking for ensuring code compiles or fails to compile as expected.

131

132

```scala { .api }

133

/**

134

* Compile-time type checking (Scala 3)

135

* @param code - Code to check for compilation

136

* @return UIO[Either[String, Unit]] - Left with error messages if compilation fails, Right with Unit if successful

137

*/

138

inline def typeCheck(inline code: String): UIO[Either[String, Unit]]

139

140

/**

141

* Compile-time type checking (Scala 2)

142

* @param code - Code to check for compilation

143

* @return UIO[Either[String, Unit]] - Left with error messages if compilation fails, Right with Unit if successful

144

*/

145

def typeCheck(code: String): UIO[Either[String, Unit]]

146

```

147

148

**Usage Examples:**

149

150

```scala

151

import zio.test._

152

153

test("type checking") {

154

for {

155

// Ensure valid code compiles

156

validResult <- typeCheck("val x: Int = 42")

157

_ <- assertTrue(validResult.isRight)

158

159

// Ensure invalid code fails to compile

160

invalidResult <- typeCheck("val x: String = 42")

161

_ <- assertTrue(invalidResult.isLeft)

162

163

// Test generic type inference

164

genericResult <- typeCheck("List(1, 2, 3).map(_ * 2)")

165

_ <- assertTrue(genericResult.isRight)

166

} yield ()

167

}

168

```

169

170

### Smart Assertion Extensions

171

172

Extension methods for navigating complex data structures in smart assertions.

173

174

```scala { .api }

175

/**

176

* Extension method for navigating data in smart assertions

177

*/

178

implicit final class SmartAssertionOps[A](private val self: A) extends AnyVal {

179

/**

180

* Transform the value using the given TestLens for navigation

181

* @param f - Function to transform TestLens

182

* @return Transformed value for assertion

183

*/

184

def is[B](f: TestLens[A] => TestLens[B]): B

185

}

186

187

/**

188

* TestLens for navigating Option values

189

*/

190

implicit final class TestLensOptionOps[A](private val self: TestLens[Option[A]]) extends AnyVal {

191

/** Transform Option to its Some value, fails if None */

192

def some: TestLens[A]

193

}

194

195

/**

196

* TestLens for navigating Either values

197

*/

198

implicit final class TestLensEitherOps[E, A](private val self: TestLens[Either[E, A]]) extends AnyVal {

199

/** Transform Either to its Left value, fails if Right */

200

def left: TestLens[E]

201

202

/** Transform Either to its Right value, fails if Left */

203

def right: TestLens[A]

204

}

205

206

/**

207

* TestLens for navigating Try values

208

*/

209

implicit final class TestLensTryOps[A](private val self: TestLens[scala.util.Try[A]]) extends AnyVal {

210

/** Transform Try to its Success value, fails if Failure */

211

def success: TestLens[A]

212

213

/** Transform Try to Throwable if Failure, fails if Success */

214

def failure: TestLens[Throwable]

215

}

216

217

/**

218

* TestLens for navigating Exit values

219

*/

220

implicit final class TestLensExitOps[E, A](private val self: TestLens[Exit[E, A]]) extends AnyVal {

221

/** Transform Exit to Throwable if die, fails otherwise */

222

def die: TestLens[Throwable]

223

224

/** Transform Exit to failure type if fail, fails otherwise */

225

def failure: TestLens[E]

226

227

/** Transform Exit to success type if succeed, fails otherwise */

228

def success: TestLens[A]

229

230

/** Transform Exit to its underlying Cause if it has one */

231

def cause: TestLens[Cause[E]]

232

233

/** Transform Exit to boolean representing if interrupted */

234

def interrupted: TestLens[Boolean]

235

}

236

```

237

238

**Usage Examples:**

239

240

```scala

241

import zio.test._

242

243

test("smart assertion navigation") {

244

val maybeUser: Option[User] = Some(User("Alice", 25))

245

val result: Either[String, Int] = Right(42)

246

val computation: Try[String] = Success("hello")

247

248

// Navigate Option values

249

assertTrue(maybeUser.is(_.some.name) == "Alice")

250

assertTrue(maybeUser.is(_.some.age) > 18)

251

252

// Navigate Either values

253

assertTrue(result.is(_.right) == 42)

254

assertTrue(result.is(_.right) > 40)

255

256

// Navigate Try values

257

assertTrue(computation.is(_.success.length) == 5)

258

assertTrue(computation.is(_.success.startsWith("h")))

259

}

260

261

test("exit navigation") {

262

val success: Exit[String, Int] = Exit.succeed(42)

263

val failure: Exit[String, Int] = Exit.fail("error")

264

265

assertTrue(success.is(_.success) == 42)

266

assertTrue(failure.is(_.failure) == "error")

267

}

268

```

269

270

### Custom Assertions

271

272

Interface for creating custom smart assertion transformations.

273

274

```scala { .api }

275

/**

276

* Interface for custom assertion transformations

277

*/

278

trait CustomAssertion[A, B] {

279

def apply(value: A): Either[String, B]

280

}

281

282

/**

283

* TestLens extension for custom assertions

284

*/

285

implicit final class TestLensAnyOps[A](private val self: TestLens[A]) extends AnyVal {

286

/** Transform value with custom assertion */

287

def custom[B](customAssertion: CustomAssertion[A, B]): TestLens[B]

288

289

/** Transform value to subtype if possible */

290

def subtype[Subtype <: A]: TestLens[Subtype]

291

292

/** Always returns true if preceding transformations succeeded */

293

def anything: TestLens[Boolean]

294

}

295

```

296

297

**Usage Examples:**

298

299

```scala

300

import zio.test._

301

302

// Custom assertion for email validation

303

val emailAssertion = new CustomAssertion[String, String] {

304

def apply(value: String): Either[String, String] =

305

if (value.contains("@")) Right(value)

306

else Left("Not a valid email")

307

}

308

309

test("custom assertions") {

310

val email = "user@example.com"

311

val invalidEmail = "notanemail"

312

313

assertTrue(email.is(_.custom(emailAssertion).nonEmpty))

314

// invalidEmail.is(_.custom(emailAssertion)) would fail the test

315

316

// Subtype checking

317

val shapes: List[Shape] = List(Circle(5), Rectangle(4, 6))

318

assertTrue(shapes.head.is(_.subtype[Circle].radius) == 5)

319

}

320

```