diff --git a/README.md b/README.md index e492001..0fa0e6a 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,35 @@ This will test `my_function` using the `Generator::strings()` generator. You can also register your own Generators using the `Annotation::register($type, $generator)` method. +## PHPUnit + +To use php-quickcheck with PHPUnit, the assertion `\QCheck\PHPUnit\Constraint\Prop` is provided. +It provides a static constructor method `Prop::check`. Similar to `Quick::check`, the method takes the size and allows also passing options if needed. + +```php +public function testStringsAreLessThanTenChars() +{ + $property = Gen::forAll([Gen::strings()], function ($s): bool { + return 10 > strlen($s); + }); + $this->assertThat($property, Prop::check(50)); // will fail +} +``` +The assertion will delegate to `Quick::check($size, $property)`, and if the function returns anything but `true`, it will display a formatted failure description. + +``` +Failed asserting that property is true. +Tests runs: 16, failing size: 15, seed: 1578486446175, smallest shrunk value(s): +array ( + 0 => , +) +``` + +If an exception is thrown or a PHPUnit assertion fails, the message will be included in the output. + +To reproduce a test result the displayed seed can be passed via `Prop::check($size, ['seed' => 1578486446175])`. + + ## Project Status PhpQuickCheck is highly experimental and in its very early stages. Only diff --git a/src/QCheck/PHPUnit/Constraint/Prop.php b/src/QCheck/PHPUnit/Constraint/Prop.php new file mode 100644 index 0000000..a187419 --- /dev/null +++ b/src/QCheck/PHPUnit/Constraint/Prop.php @@ -0,0 +1,69 @@ +size = $n; + $this->opts = $opts; + } + + public static function check($n = 100, array $opts = []) + { + return new self($n, $opts); + } + + public function evaluate($prop, string $description = '', bool $returnResult = false) + { + $result = Quick::check($this->size, $prop, $this->opts); + return parent::evaluate($result, $description, $returnResult); + } + + protected function matches($other): bool + { + return @$other['result'] === true; + } + + public function toString(): string + { + return 'property is true'; + } + + protected function failureDescription($other): string + { + return $this->toString(); + } + + protected function additionalFailureDescription($other): string + { + return sprintf( + "%sTests runs: %d, failing size: %d, seed: %s, smallest shrunk value(s):\n%s", + $this->extractExceptionMessage($other['result']), + $other['num_tests'], + $other['failing_size'], + $other['seed'], + var_export($other['shrunk']['smallest'], true) + ); + } + + private function extractExceptionMessage($result): string + { + return $result instanceof \Exception ? $result->getMessage() . "\n" : ''; + } + +}