Classify
Rasuvaeff\PropertyTesting\Classify
Class — Package: property-testing-core — Source — Version: v1.0.0-1-g88fdee2
Records distribution labels for the current property run so the runner can report how often each case occurred. Use it to confirm a property is not passing vacuously — that the generators actually exercise the interesting inputs.
#[Property(runs: 500)]
public function holds(int $n): void
{
Classify::when($n === 0, 'zero');
Classify::when($n < 0, 'negative');
Classify::label($n % 2 === 0 ? 'even' : 'odd');
// ... assertions ...
}After a fully passing property the runner prints the share of runs that hit each label. A label recorded several times within one run still counts once for that run.
State is per-run and process-local: the runner clears it before each run via beginRun() and drains it via flushRun(). Property runs are sequential, so the static buffer is never shared concurrently.
Methods
label()
static label(string $label): voidRecord $label for the current run.
when()
static when(bool $condition, string $label): voidRecord $label for the current run only when $condition holds.
cover()
static cover(
bool $condition,
string $label,
float $minPercent,
): voidLike when(), but additionally REQUIRES the label to occur in at least $minPercent of the property's passing runs. When the requirement is not met the property fails with a CoverageViolationException even though every run passed — turning "the distribution looks wrong" from a printed hint into a CI failure.
Classify::cover($n % 2 === 0, 'even', 30.0);The threshold belongs to the label, not to the call: covering the same label twice in one run with different percentages leaves the last one standing.
tabulate()
static tabulate(string $table, string|list<string> $tags): voidRecord one or more tags of $table for the current run: the categories a run belongs to at once, aggregated into a per-table tally with the pairwise intersections of tags that were hit together. Observability only — no minimum share, no verdict; cover() stays the one enforcement tool:
$table— The table the tags belong to.$tags— One tag, or every tag the run hits at once.
Classify::tabulate('payload', $size < 1024 ? 'small' : 'large'); Classify::tabulate('features', array_keys(array_filter([ 'compressed' => $compressed, 'retried' => $attempt > 1, ])));
A tag recorded several times within one run counts once for that run, like a label. An empty tag list records nothing.
beginRun()
static beginRun(): voidClear the labels and tables of the previous run.
flushRun()
static flushRun(): arrayReturn the labels recorded during the current run and clear the buffer.
flushTables()
static flushTables(): arrayReturn the tables recorded during the current run — table name to the tags hit, as the strings the body recorded — and clear them.
flushRequirements()
static flushRequirements(): arrayReturn the coverage requirements registered during the property and clear them. The runner drains this once after the run loop (and defensively before it, in case a previous property aborted mid-flight).