PHP code example of rasuvaeff / property-testing-core
1. Go to this page and download the library: Download rasuvaeff/property-testing-core library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
rasuvaeff / property-testing-core example snippets
use Rasuvaeff\PropertyTesting\Gen;
use Rasuvaeff\PropertyTesting\Runner\CallableTrialExecutor;
use Rasuvaeff\PropertyTesting\Runner\Falsified;
use Rasuvaeff\PropertyTesting\Runner\PropertyConfig;
use Rasuvaeff\PropertyTesting\Runner\PropertyDefinition;
use Rasuvaeff\PropertyTesting\Runner\PropertyRunner;
$definition = new PropertyDefinition(
id: 'demo::everyIntStaysBelowHundred',
name: 'everyIntStaysBelowHundred',
generators: ['value' => Gen::intBetween(0, 10_000)],
parameterNames: ['value'],
config: new PropertyConfig(runs: 200, seed: 42),
);
$result = (new PropertyRunner())->run($definition, new CallableTrialExecutor(
static function (int $value): void {
if ($value >= 100) {
throw new RuntimeException(sprintf('%d is not below 100', $value));
}
},
));
if ($result instanceof Falsified) {
$example = $result->counterExample();
// $example->seed, $example->originalArguments, $example->shrunkArguments, ...
fwrite(STDERR, $result->failure()->getMessage());
}
use Rasuvaeff\PropertyTesting\Arbitrary\IntArbitrary;
use Rasuvaeff\PropertyTesting\Generate;
public function delayStaysWithinCap(
#[Generate(new IntArbitrary(0, 10_000))]
int $base,
#[Generate([Generators::class, 'email'])]
string $to,
): void {}
Gen::swarm(Gen::oneOf('push', 'pop', 'flush')); // one case sees, say, only 'pop' and 'flush'
Gen::swarm(Gen::commands($model, $commands)); // one sequence uses a subset of the commands
Gen::flatMap(
Gen::nonEmptyArrayOf(Gen::int()),
static fn(array $items): ArbitraryInterface => Gen::tuple(
Gen::constant($items),
Gen::intBetween(0, count($items) - 1), // always a valid index
),
);
$interval = Gen::composite(static fn (Draw $d): Interval => new Interval(
$min = $d->draw(Gen::datetime()),
$d->draw(Gen::datetime(min: $min)), // sees the prior draw
));
static function (int $attempt, \Random\Randomizer $randomizer): void {
$delay = (new JitteredBackoff($randomizer))->delayMs($attempt);
Assert::true($delay <= 60_000);
}
static function (int $a, int $b, int $c): void {
Target::maximize('sum', $a + $b + $c);
Assert::true($a + $b + $c <= 2_900); // 0.17% of the space
}
new PropertyConfig(derandomize: true); // the same id always selects the same inputs
$counterExample->path; // 'value:2/value:2/value:4/value:4'
new PropertyConfig(seed: 1, path: 'value:2/value:2/value:4/value:4');
new PropertyConfig(shrink: ShrinkMode::Off); // report the counterexample as generated
new PropertyConfig(shrinkBudgetMs: 500); // descend for at most 500 ms, keep the best so far
new PropertyConfig(phases: [Phase::Examples, Phase::Corpus]); // fast pull-request gate
new PropertyConfig(); // every phase (the default)
$corpus = new RedisCorpus(new PhpRedisCorpusClient($redis));
$definition = new PropertyDefinition(
id: 'demo::stackBehavesLikeItsModel',
name: 'stackBehavesLikeItsModel',
generators: ['sequence' => Gen::commands([], [
Gen::map(Gen::intBetween(0, 99), static fn(int $v): Command => new Push($v)),
Gen::constant(new Pop()),
])],
parameterNames: ['sequence'],
config: new PropertyConfig(runs: 200),
);
$result = (new PropertyRunner())->run($definition, new CallableTrialExecutor(
static function (CommandSequence $sequence): void {
StateMachine::check($sequence, static fn(): Stack => new Stack());
},
));
final class QueueMachine
{
private array $model = [];
public function __construct(private readonly Queue $sut) {}
#[Rule]
public function enqueue(int $value): void
{
$this->sut->push($value);
$this->model[] = $value;
}
#[Rule]
#[Precondition('notEmpty')]
public function dequeue(): void
{
Assert::same($this->sut->pop(), array_shift($this->model));
}
public function notEmpty(): bool { return $this->model !== []; }
#[Invariant]
public function sizeMatches(): void
{
Assert::same($this->sut->size(), count($this->model));
}
}
// generators: ['sequence' => Gen::rules(QueueMachine::class, maxLength: 50)]
static function (RuleSequence $sequence): void {
$sequence->run(static fn (): QueueMachine => new QueueMachine(new Queue()));
}
text
PHP 8.3 Suite::{closure}
PHP 8.4+ Suite::{closure:/app/tests/StackTest.php:19}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.