Remove year from copyright
Fix copy/paste error
Added ADRs and meagerfile
ADRs | Meagerfile | License (MIT) | Contributing
Test data generation library for Scala 3. meager-datagen
provides composable
generator definitions that can be reused across tests.
This library is not yet published.
object Meager {
val Test: ModuleID =
"meager" %% "meager-datagen-v0" % "0.1.0-SNAPSHOT"
}
The standard way to use meager-datagen
is to import the entire package, which
pulls in Gen[A]
, Generated[A]
and Datagen[A, -I]
:
import io.meager.datagen.v0.*
For the following examples, the following types (abbreviated) are relevant:
opaque type Name = String
opaque type DateOfBirth = LocalDate
opaque type Karma = Long
enum Role:
case Regular, Mod, Admin
case class User(
name: Name,
dateOfBirth: DateOfBirth,
karma: Karma,
role: Role
)
One way to go about this is to define generators for each type and then compose
those generators for User
:
import io.meager.datagen.v0._
import io.meager.datagen.v0.generators.MinMax
val nameGen: Gen[Name] =
Gen.string.alpha(4, 16).map(Name(_))
val dateOfBirthGen: Gen[LocalDate] =
Gen.date.beforeToday(
days = MinMax.Zero,
months = MinMax.nonNegative(0, 11),
years = MinMax.nonNegative(18, 80)
).map(DateOfBirth(_))
val karmaGen: Gen[Karma] =
Gen.long.inRange(-100L, 100L).map(Karma(_))
val roleGen: Gen[Role] =
Gen.oneOf.fixedChoices(Role.Regular, Role.Mod, Role.Admin)
and the composition:
val userGen: Gen[User] =
for
name <- nameGen
dateOfBirth <- dateOfBirthGen
karma <- karmaGen
role <- roleGen
yield User(name, dateOfBirth, karma, role)
Generators may also be defined inline if separate definitions are not useful:
val userGen: Gen[User] =
for
name <- Gen.string.alpha(4, 16).map(Name(_))
dateOfBirth <- dateOfBirthGen
karma <- Gen.long.inRange(-100L, 100L).map(Karma(_))
role <- roleGen
yield User(name, dateOfBirth, karma, role)
Once that generator exists, users may be generated:
val user: User = userGen.gen()
The Generated
type class can be used as well:
given Generated[User] = Generated.of(userGen)
val user2: User = Generated[User].generate()
What if we want a way to generate users randomly, but always require the caller to specify a user role? This can be accomplished by requiring input when generating data:
val roleUserGen: Datagen[User, Role] =
for
name <- Gen.string.alpha(4, 16).map(Name(_))
dateOfBirth <- dateOfBirthGen
karma <- Gen.long.inRange(-100L, 100L).map(Karma(_))
yield (role: Role) => User(name, dateOfBirth, karma, role)
The usage of this type is different and does not support Generated
:
val admin: User = roleUserGen.generate(Role.Admin)
val mod: User = roleUserGen.generate(Role.Mod)
val regular: User = roleUserGen.generate(Role.Regular)
For a complete list of generators supported out of the box, please refer to the Gen definition, which enumerates and documents all options.