Gen
Rasuvaeff\PropertyTesting\Gen
Class — Source
Facade with static factories for the built-in ArbitraryInterfaces.
Each factory returns a ready-to-use arbitrary; values are never generated directly through Gen — that happens inside the property runner, which threads the seedable Random through every generator so runs are reproducible. The one exception is sample(), a debugging aid that eagerly generates values from a given arbitrary.
Methods
int()
static int(): Arbitrary\IntArbitraryIntegers spanning PHP_INT_MIN..PHP_INT_MAX.
intBetween()
static intBetween(int $min, int $max): Arbitrary\IntArbitraryintPositive()
static intPositive(): Arbitrary\IntArbitraryPositive integers (1..PHP_INT_MAX).
float()
static float(): Arbitrary\FloatArbitraryFloats in the half-open range [0.0, 1.0).
floatBetween()
static floatBetween(float $min, float $max): Arbitrary\FloatArbitrarybool()
static bool(): Arbitrary\BoolArbitrarystring()
static string(): Arbitrary\StringArbitraryUnicode strings of length 0..100.
stringAscii()
static stringAscii(): Arbitrary\StringArbitraryPrintable ASCII strings of length 0..100.
stringOf()
static stringOf(int $minLength, int $maxLength): Arbitrary\StringArbitrarychar()
static char(): Arbitrary\StringArbitraryA single printable ASCII character.
stringFrom()
static stringFrom(
string $alphabet,
int $minLength,
int $maxLength,
): Arbitrary\CharsetStringArbitraryStrings whose characters come from a fixed alphabet (split per Unicode codepoint). Shrinks by length toward '', then each character toward the first alphabet character — list simpler characters first.
bytes()
static bytes(int $minLength, int $maxLength): Arbitrary\BytesArbitraryRaw byte strings (every byte 0..255). Shrinks by length toward '', then each byte toward "\x00".
arrayOf()
static arrayOf(
ArbitraryInterface $element,
int $minSize,
int $maxSize,
): Arbitrary\ArrayArbitraryLists whose elements are drawn from $element.
nonEmptyArrayOf()
static nonEmptyArrayOf(
ArbitraryInterface $element,
int $maxSize,
): Arbitrary\ArrayArbitraryNon-empty lists whose elements are drawn from $element.
uniqueArrayOf()
static uniqueArrayOf(
ArbitraryInterface $element,
int $minSize,
int $maxSize,
): Arbitrary\UniqueArrayArbitraryLists of pairwise-distinct elements (strict comparison) drawn from $element. Element shrinking keeps the list distinct; the result may be smaller than the drawn size when the element space runs out of fresh values, but never below $minSize — an unreachable minimum throws GenerationExhausted.
dictOf()
static dictOf(
ArbitraryInterface $key,
ArbitraryInterface $value,
int $minSize,
int $maxSize,
): Arbitrary\DictionaryArbitraryAssociative arrays (maps) with keys from $key and values from $value. Keys must be int or string; only distinct keys are kept, so the result may be smaller than the drawn size when the key space runs out, but never below $minSize — an unreachable minimum throws GenerationExhausted.
record()
static record(array $shape): Arbitrary\RecordArbitraryFixed-shape associative array: each field is generated from its own arbitrary, keyed by field name. The property receives a single string-keyed array; shrinking reduces each field through its arbitrary while keeping the key set fixed.
oneOf()
static oneOf(mixed $values): Arbitrary\OneOfArbitraryPicks one of the given values at random.
elements()
static elements(array $values): Arbitrary\OneOfArbitraryPicks one value at random from an array (the array form of oneOf()).
constant()
static constant(mixed $value): Arbitrary\ConstantArbitraryAlways produces $value; does not shrink.
enum()
static enum(string $enum): Arbitrary\OneOfArbitraryOne case of a PHP enum, in declaration order. Shrinks toward earlier-declared cases, so declare simpler cases first.
floatSpecial()
static floatSpecial(): Arbitrary\OneOfArbitrarySpecial float values (NaN, ±INF, -0.0 and the representation edges) where float bugs cluster — an opt-in complement to float(), which stays inside its finite range. Shrinks toward earlier-listed specials.
intRange()
static intRange(int $min, int $max): Arbitrary\FlatMappedArbitraryOrdered integer pairs [lo, hi] with $min <= lo <= hi <= $max — the "range/interval" input without an Assume::that() discard. Built on flatMap(), so both bounds shrink while lo <= hi always holds.
recursive()
static recursive(
ArbitraryInterface $leaf,
Closure $wrap,
int $maxDepth,
): ArbitraryInterfaceRecursive structures with a bounded depth: $wrap receives the arbitrary for the previous level and returns the next one (e.g. wrap a value in an array). At every level generation picks the leaf or the wrapped branch with equal odds, so nesting is possible but not forced. Keep the branch fan-out small (bounded array sizes) — breadth multiplies per level.
nullable()
static nullable(ArbitraryInterface $inner): Arbitrary\NullableArbitraryYields null or a value from $inner with roughly even odds.
map()
static map(ArbitraryInterface $inner, Closure $map): Arbitrary\MappedArbitraryTransforms each value produced by $inner through a pure function. Shrinking happens in the source domain and the function is re-applied, so mapped values shrink through the inner arbitrary's tree.
flatMap()
static flatMap(
ArbitraryInterface $inner,
Closure $flatMap,
): Arbitrary\FlatMappedArbitraryDependent generators (aka bind): feeds each value produced by $inner into $flatMap, which returns the arbitrary generating the final value. Use it when one input's domain depends on another (e.g. an array plus a valid index into it) instead of discarding invalid combinations with Assume::that().
filter()
static filter(
ArbitraryInterface $inner,
Closure $predicate,
): Arbitrary\FilteredArbitraryGenerates values from $inner, retrying until $predicate holds.
draw()
static draw(ArbitraryInterface $arbitrary): mixedIn-body dependent draw: generates one value from $arbitrary inside the property body — for when several dependent values make nested flatMap() awkward. The domain may depend on anything already in scope, including previously drawn values:
#[Property(runs: 200)]
public function sliceIsContained(array $xs): void
{
$from = Gen::draw(Gen::intBetween(0, count($xs)));
$to = Gen::draw(Gen::intBetween($from, count($xs)));
// ... assertions on array_slice($xs, $from, $to - $from) ...
}Drawn values shrink together with the parameters: the runner records every draw on a replay tape, shrinks each recorded draw through its own tree, and re-runs the body with the tape replayed by position. A run that draws past the tape's end (control flow changed under a smaller prefix) generates the extra values anew. Counterexamples report draws as draw#1, draw#2, ... alongside the named parameters.
Only valid while the property runner executes the body; anywhere else it throws.
tuple()
static tuple(ArbitraryInterface $elements): Arbitrary\TupleArbitraryFixed-arity tuple: one value per element arbitrary, in order. The property receives the tuple as a single array argument; shrinking reduces each position through its own arbitrary while keeping the arity fixed.
frequency()
static frequency(iterable $pairs): Arbitrary\FrequencyArbitraryWeighted choice among [weight, arbitrary] pairs: a branch is picked with probability proportional to its weight, then produces the value. Shrinking stays within the branch that generated the value.
uuid()
static uuid(): Arbitrary\UuidArbitraryCanonical RFC 4122 version 4 UUID strings. Does not shrink.
datetime()
static datetime(
?DateTimeImmutable $min,
?DateTimeImmutable $max,
): Arbitrary\DateTimeArbitraryUTC DateTimeImmutable values with a timestamp in the inclusive range [$min, $max] (defaults: 1970-01-01 .. 2100-01-01). Shrinks toward the Unix epoch, clamped to the range.
ipv4()
static ipv4(): Arbitrary\MappedArbitraryIPv4 dotted-quad address strings ("0.0.0.0".."255.255.255.255"). Each octet shrinks toward 0 through its own integer tree.
email()
static email(): Arbitrary\MappedArbitrarySyntactically valid local@label.tld email addresses over a lowercase alphanumeric alphabet and a small TLD set. Shrinks toward the shortest local part / label and the first TLD.
url()
static url(): Arbitrary\MappedArbitraryHTTP/HTTPS URLs scheme://host.tld[/segment...] over a lowercase alphanumeric alphabet. Shrinks toward http://a.com (no path).
json()
static json(int $maxDepth): ArbitraryInterfaceA JSON-encodable value — null, bool, int, float, string, or nested lists/objects thereof — bounded to $maxDepth levels of nesting. Produces the decoded PHP value; use jsonString() for the encoded text.
jsonString()
static jsonString(int $maxDepth): Arbitrary\MappedArbitraryThe JSON text of json() (json_encode of each generated value), for exercising JSON parsers and decoders.
regex()
static regex(string $pattern, int $maxRepeat): ArbitraryInterfaceStrings matching a regular-expression subset. The pattern is compiled to ordinary combinators, so matches shrink toward shorter/simpler strings.
Supported: literals, ., character classes [...] (ranges, negation, \d\w\s and their negations), the escapes \d\w\s\D\W\S\t\n\r plus \-escaped metacharacters, quantifiers * + ? {n} {n,} {n,m}, alternation |, and groups (...) / (?:...). A single leading ^ and trailing $ are accepted as no-ops. Anchors elsewhere, backreferences, lookaround, named/inline groups, and flags throw an \InvalidArgumentException naming the construct.
$maxRepeat— Upper bound generation uses for unbounded quantifiers (*,+,{n,}).
stringMatching()
static stringMatching(string $pattern, int $maxRepeat): ArbitraryInterfaceAlias of regex() for parity with fast-check/Hypothesis naming.
commands()
static commands(
mixed $initialModel,
array $commandGenerators,
int $minLength,
int $maxLength,
): Arbitrary\CommandSequenceArbitraryA valid \Rasuvaeff\PropertyTesting\StateMachine\Command sequence for stateful / model-based testing. Starting from $initialModel, each step draws a command generator and appends its command when the command's precondition holds in the running model, advancing the model — so the sequence is valid by construction. Shrinking drops individual steps and simplifies each command through its own tree. A sequence shorter than $minLength (no applicable command reached it) throws GenerationExhausted.
Feed the generated \Rasuvaeff\PropertyTesting\StateMachine\CommandSequence to \Rasuvaeff\PropertyTesting\StateMachine\StateMachine::check() in the property body, passing a factory that builds a fresh system under test.
$commandGenerators— Each must produce a \Rasuvaeff\PropertyTesting\StateMachine\Command.
sample()
static sample(
ArbitraryInterface $arbitrary,
int $count,
int $seed,
): arrayEagerly generate $count values from $arbitrary using a fixed $seed. A debugging aid for inspecting a generator's output and distribution; unlike the other factories it returns values, not an arbitrary.
sampleShrinks()
static sampleShrinks(
ArbitraryInterface $arbitrary,
int $seed,
int $limit,
): arrayEagerly generate one value from $arbitrary for a fixed $seed and collect its first direct shrink candidates. A debugging aid for authors of custom ArbitraryInterfaces: eyeball what the shrink tree offers before wiring the arbitrary into a property.