or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

arbitrary.mdcogen.mdgenerators.mdindex.mdproperties.mdproperty-collections.mdshrinking.mdstateful-testing.mdtest-execution.md

arbitrary.mddocs/

0

# Automatic Value Generation

1

2

The ScalaCheck Arbitrary framework provides type-directed generator instances for automatic property parameterization. It eliminates the need to explicitly specify generators for common types and enables seamless integration with the property testing system.

3

4

## Capabilities

5

6

### Core Arbitrary Class

7

8

The fundamental type class that wraps generators and provides implicit resolution.

9

10

```scala { .api }

11

sealed abstract class Arbitrary[T] {

12

def arbitrary: Gen[T]

13

}

14

15

object Arbitrary {

16

def apply[T](g: => Gen[T]): Arbitrary[T]

17

def arbitrary[T](implicit a: Arbitrary[T]): Gen[T]

18

}

19

```

20

21

**Usage Examples:**

22

```scala

23

// Create custom Arbitrary instance

24

case class Person(name: String, age: Int)

25

implicit val arbPerson: Arbitrary[Person] = Arbitrary {

26

for {

27

name <- Gen.alphaStr.suchThat(_.nonEmpty)

28

age <- Gen.choose(0, 120)

29

} yield Person(name, age)

30

}

31

32

// Use implicit generator

33

val personProperty = forAll { (p: Person) =>

34

p.age >= 0 && p.name.nonEmpty

35

}

36

37

// Get generator explicitly

38

val personGen: Gen[Person] = Arbitrary.arbitrary[Person]

39

```

40

41

### Primitive Type Instances

42

43

Implicit generators for basic Scala and Java primitive types.

44

45

```scala { .api }

46

implicit val arbBool: Arbitrary[Boolean]

47

implicit val arbInt: Arbitrary[Int]

48

implicit val arbLong: Arbitrary[Long]

49

implicit val arbFloat: Arbitrary[Float]

50

implicit val arbDouble: Arbitrary[Double]

51

implicit val arbChar: Arbitrary[Char]

52

implicit val arbByte: Arbitrary[Byte]

53

implicit val arbShort: Arbitrary[Short]

54

implicit val arbUnit: Arbitrary[Unit]

55

implicit val arbAnyVal: Arbitrary[AnyVal]

56

```

57

58

**Usage Examples:**

59

```scala

60

// These work automatically due to implicit instances

61

val intProp = forAll { (x: Int) => x + 0 == x }

62

val boolProp = forAll { (b: Boolean) => b || !b }

63

val charProp = forAll { (c: Char) => c.toString.length == 1 }

64

val floatProp = forAll { (f: Float) => !f.isNaN ==> (f + 0.0f == f) }

65

```

66

67

### String and Text Types

68

69

Generators for various string and symbolic text representations.

70

71

```scala { .api }

72

implicit val arbString: Arbitrary[String]

73

implicit val arbSymbol: Arbitrary[Symbol]

74

```

75

76

**Usage Examples:**

77

```scala

78

val stringProp = forAll { (s: String) =>

79

s.reverse.reverse == s

80

}

81

82

val symbolProp = forAll { (sym: Symbol) =>

83

Symbol(sym.name) == sym

84

}

85

```

86

87

### Numeric Types

88

89

Arbitrary instances for big numeric types and Java numeric wrappers.

90

91

```scala { .api }

92

implicit val arbBigInt: Arbitrary[BigInt]

93

implicit val arbBigDecimal: Arbitrary[BigDecimal]

94

implicit val arbNumber: Arbitrary[Number]

95

```

96

97

**Usage Examples:**

98

```scala

99

val bigIntProp = forAll { (x: BigInt, y: BigInt) =>

100

x + y == y + x

101

}

102

103

val bigDecimalProp = forAll { (x: BigDecimal) =>

104

x * BigDecimal(1) == x

105

}

106

```

107

108

### Date and Time Types

109

110

Generators for temporal types including legacy Java date/time and Scala durations.

111

112

```scala { .api }

113

implicit val arbDate: Arbitrary[java.util.Date]

114

implicit val arbCalendar: Arbitrary[java.util.Calendar]

115

implicit val arbFiniteDuration: Arbitrary[FiniteDuration]

116

implicit val arbDuration: Arbitrary[Duration]

117

```

118

119

**Usage Examples:**

120

```scala

121

val dateProp = forAll { (d: java.util.Date) =>

122

new java.util.Date(d.getTime) == d

123

}

124

125

val durationProp = forAll { (d1: FiniteDuration, d2: FiniteDuration) =>

126

(d1 + d2) >= d1 && (d1 + d2) >= d2

127

}

128

```

129

130

### Exception Types

131

132

Generators for exception and error hierarchies.

133

134

```scala { .api }

135

implicit val arbThrowable: Arbitrary[Throwable]

136

implicit val arbException: Arbitrary[Exception]

137

implicit val arbError: Arbitrary[Error]

138

```

139

140

**Usage Examples:**

141

```scala

142

val exceptionProp = forAll { (e: Exception) =>

143

e.getMessage != null || e.getMessage == null // Either is valid

144

}

145

```

146

147

### Miscellaneous Types

148

149

Generators for UUIDs, bit sets, and other utility types.

150

151

```scala { .api }

152

implicit val arbUuid: Arbitrary[java.util.UUID]

153

implicit val arbBitSet: Arbitrary[collection.BitSet]

154

```

155

156

**Usage Examples:**

157

```scala

158

val uuidProp = forAll { (u: java.util.UUID) =>

159

java.util.UUID.fromString(u.toString) == u

160

}

161

162

val bitSetProp = forAll { (bs: collection.BitSet) =>

163

bs union bs == bs

164

}

165

```

166

167

### Higher-Order Type Instances

168

169

Automatic generator derivation for generic types and type constructors.

170

171

```scala { .api }

172

implicit def arbOption[T](implicit a: Arbitrary[T]): Arbitrary[Option[T]]

173

implicit def arbEither[T, U](implicit at: Arbitrary[T], au: Arbitrary[U]): Arbitrary[Either[T, U]]

174

implicit def arbTry[T](implicit a: Arbitrary[T]): Arbitrary[Try[T]]

175

implicit def arbFuture[T](implicit a: Arbitrary[T]): Arbitrary[Future[T]]

176

```

177

178

**Usage Examples:**

179

```scala

180

val optionProp = forAll { (opt: Option[String]) =>

181

opt.map(_.length).getOrElse(0) >= 0

182

}

183

184

val eitherProp = forAll { (e: Either[String, Int]) =>

185

e.isLeft || e.isRight

186

}

187

188

val tryProp = forAll { (t: Try[Int]) =>

189

t.isSuccess || t.isFailure

190

}

191

```

192

193

### Collection Type Instances

194

195

Automatic generator derivation for various collection types.

196

197

```scala { .api }

198

implicit def arbContainer[C[_], T](

199

implicit a: Arbitrary[T],

200

b: Buildable[T, C[T]]

201

): Arbitrary[C[T]]

202

203

implicit def arbContainer2[C[_, _], T, U](

204

implicit at: Arbitrary[T],

205

au: Arbitrary[U],

206

b: Buildable[(T, U), C[T, U]]

207

): Arbitrary[C[T, U]]

208

```

209

210

**Usage Examples:**

211

```scala

212

val listProp = forAll { (l: List[Int]) =>

213

l.reverse.reverse == l

214

}

215

216

val vectorProp = forAll { (v: Vector[String]) =>

217

v.length >= 0

218

}

219

220

val mapProp = forAll { (m: Map[String, Int]) =>

221

m.keys.size <= m.size

222

}

223

224

val setProp = forAll { (s: Set[Double]) =>

225

s union s == s

226

}

227

```

228

229

### Function Type Instances

230

231

Generators for function types using co-generators.

232

233

```scala { .api }

234

implicit def arbFunction0[T](implicit a: Arbitrary[T]): Arbitrary[() => T]

235

implicit def arbPartialFunction[A, B](

236

implicit aa: Arbitrary[A],

237

ca: Cogen[A],

238

ab: Arbitrary[B]

239

): Arbitrary[PartialFunction[A, B]]

240

```

241

242

**Usage Examples:**

243

```scala

244

val function0Prop = forAll { (f: () => Int) =>

245

f() == f() // Should be deterministic

246

}

247

248

val pfProp = forAll { (pf: PartialFunction[Int, String], x: Int) =>

249

pf.isDefinedAt(x) ==> (pf(x) != null)

250

}

251

```

252

253

### Java Enum Support

254

255

Automatic generator derivation for Java enumeration types.

256

257

```scala { .api }

258

implicit def arbEnum[A <: java.lang.Enum[A]](

259

implicit tag: reflect.ClassTag[A]

260

): Arbitrary[A]

261

```

262

263

**Usage Examples:**

264

```scala

265

// For Java enum types

266

enum Color { RED, GREEN, BLUE }

267

268

val colorProp = forAll { (c: Color) =>

269

c == Color.RED || c == Color.GREEN || c == Color.BLUE

270

}

271

```

272

273

### Test Infrastructure Types

274

275

Generators for ScalaCheck's own types, useful for meta-testing.

276

277

```scala { .api }

278

implicit val arbProp: Arbitrary[Prop]

279

implicit val arbTestParameters: Arbitrary[Test.Parameters]

280

implicit val arbGenParams: Arbitrary[Gen.Parameters]

281

implicit def arbGen[T](implicit a: Arbitrary[T]): Arbitrary[Gen[T]]

282

```

283

284

**Usage Examples:**

285

```scala

286

val propProp = forAll { (p: Prop) =>

287

// Meta-property: properties should be checkable

288

try { p.check(); true } catch { case _: Exception => true }

289

}

290

291

val genProp = forAll { (g: Gen[Int]) =>

292

g.sample.isDefined || g.sample.isEmpty

293

}

294

```

295

296

## Custom Arbitrary Instances

297

298

### Simple Custom Types

299

300

```scala

301

case class Email(value: String)

302

303

implicit val arbEmail: Arbitrary[Email] = Arbitrary {

304

for {

305

user <- Gen.alphaNumStr.suchThat(_.nonEmpty)

306

domain <- Gen.alphaNumStr.suchThat(_.nonEmpty)

307

tld <- Gen.oneOf("com", "org", "net", "edu")

308

} yield Email(s"$user@$domain.$tld")

309

}

310

```

311

312

### Recursive Data Structures

313

314

```scala

315

sealed trait Tree[+A]

316

case class Leaf[A](value: A) extends Tree[A]

317

case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]

318

319

implicit def arbTree[A](implicit a: Arbitrary[A]): Arbitrary[Tree[A]] = Arbitrary {

320

val genLeaf = a.arbitrary.map(Leaf(_))

321

322

def genBranch(size: Int): Gen[Tree[A]] =

323

if (size <= 0) genLeaf

324

else Gen.oneOf(

325

genLeaf,

326

for {

327

left <- genBranch(size / 2)

328

right <- genBranch(size / 2)

329

} yield Branch(left, right)

330

)

331

332

Gen.sized(genBranch)

333

}

334

```

335

336

### Constrained Generation

337

338

```scala

339

case class PositiveInt(value: Int)

340

341

implicit val arbPositiveInt: Arbitrary[PositiveInt] = Arbitrary {

342

Gen.choose(1, Int.MaxValue).map(PositiveInt)

343

}

344

345

case class NonEmptyList[A](values: List[A])

346

347

implicit def arbNonEmptyList[A](implicit a: Arbitrary[A]): Arbitrary[NonEmptyList[A]] = Arbitrary {

348

Gen.nonEmptyListOf(a.arbitrary).map(NonEmptyList(_))

349

}

350

```

351

352

### Complex Business Objects

353

354

```scala

355

case class User(

356

id: Long,

357

username: String,

358

email: String,

359

age: Int,

360

roles: Set[String],

361

settings: Map[String, String]

362

)

363

364

implicit val arbUser: Arbitrary[User] = Arbitrary {

365

for {

366

id <- Gen.posNum[Long]

367

username <- Gen.alphaNumStr.suchThat(s => s.length >= 3 && s.length <= 20)

368

email <- Arbitrary.arbitrary[Email].map(_.value)

369

age <- Gen.choose(13, 120)

370

roleCount <- Gen.choose(1, 5)

371

roles <- Gen.listOfN(roleCount, Gen.oneOf("user", "admin", "moderator", "guest"))

372

.map(_.toSet)

373

settingCount <- Gen.choose(0, 10)

374

settingKeys <- Gen.listOfN(settingCount, Gen.alphaStr.suchThat(_.nonEmpty))

375

settingValues <- Gen.listOfN(settingCount, Gen.alphaNumStr)

376

settings = settingKeys.zip(settingValues).toMap

377

} yield User(id, username, email, age, roles, settings)

378

}

379

```

380

381

## Arbitrary Resolution Patterns

382

383

### Type Class Derivation Chain

384

385

```scala

386

// Automatic derivation works through implicit chains

387

val nestedProp = forAll { (data: Map[String, List[Option[Either[Int, String]]]]) =>

388

// This works because:

389

// 1. Arbitrary[Int] and Arbitrary[String] exist

390

// 2. Arbitrary[Either[Int, String]] is derived

391

// 3. Arbitrary[Option[Either[Int, String]]] is derived

392

// 4. Arbitrary[List[Option[Either[Int, String]]]] is derived

393

// 5. Arbitrary[Map[String, List[Option[Either[Int, String]]]]] is derived

394

data.size >= 0

395

}

396

```

397

398

### Manual Generator Override

399

400

```scala

401

// Sometimes you want a specific generator for a property

402

val customProp = forAll(Gen.choose(1, 10)) { (smallInt: Int) =>

403

// Uses explicit generator instead of Arbitrary[Int]

404

smallInt >= 1 && smallInt <= 10

405

}

406

407

// Mix explicit and implicit generators

408

val mixedProp = forAll(Gen.choose(1, 100), Arbitrary.arbitrary[String]) { (smallInt, str) =>

409

smallInt.toString.length <= str.length || str.isEmpty

410

}

411

```

412

413

### Conditional Arbitrary Instances

414

415

```scala

416

// Provide different generators based on type constraints

417

implicit def arbOrderedPair[T](implicit a: Arbitrary[T], ord: Ordering[T]): Arbitrary[(T, T)] = Arbitrary {

418

for {

419

x <- a.arbitrary

420

y <- a.arbitrary

421

} yield if (ord.lt(x, y)) (x, y) else (y, x)

422

}

423

```

424

425

### Java Time Support

426

427

ScalaCheck provides built-in Arbitrary instances for Java 8 time types through the `org.scalacheck.time` package.

428

429

```scala { .api }

430

// Import for Java Time support

431

import org.scalacheck.time._

432

433

// Date and Time Types

434

implicit val arbDuration: Arbitrary[java.time.Duration]

435

implicit val arbInstant: Arbitrary[java.time.Instant]

436

implicit val arbLocalDate: Arbitrary[java.time.LocalDate]

437

implicit val arbLocalTime: Arbitrary[java.time.LocalTime]

438

implicit val arbLocalDateTime: Arbitrary[java.time.LocalDateTime]

439

implicit val arbOffsetTime: Arbitrary[java.time.OffsetTime]

440

implicit val arbOffsetDateTime: Arbitrary[java.time.OffsetDateTime]

441

implicit val arbZonedDateTime: Arbitrary[java.time.ZonedDateTime]

442

443

// Period and Year Types

444

implicit val arbPeriod: Arbitrary[java.time.Period]

445

implicit val arbYear: Arbitrary[java.time.Year]

446

implicit val arbYearMonth: Arbitrary[java.time.YearMonth]

447

implicit val arbMonthDay: Arbitrary[java.time.MonthDay]

448

449

// Zone Types

450

implicit val arbZoneOffset: Arbitrary[java.time.ZoneOffset]

451

implicit val arbZoneId: Arbitrary[java.time.ZoneId]

452

```

453

454

**Usage Examples:**

455

```scala

456

import org.scalacheck.time._

457

import java.time._

458

459

val timestampProp = forAll { (instant: Instant) =>

460

instant.getEpochSecond >= Instant.MIN.getEpochSecond &&

461

instant.getEpochSecond <= Instant.MAX.getEpochSecond

462

}

463

464

val dateProp = forAll { (date: LocalDate) =>

465

date.isAfter(LocalDate.MIN) || date.isEqual(LocalDate.MIN)

466

}

467

468

val durationProp = forAll { (d1: Duration, d2: Duration) =>

469

d1.plus(d2).minus(d1) == d2

470

}

471

472

val zonedTimeProp = forAll { (zdt: ZonedDateTime) =>

473

zdt.toInstant.atZone(zdt.getZone) == zdt

474

}

475

```