Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  and email domain cannot contain more than 63 chars
  allow to configure the number of iterations via an env var
  diversify the tested combinations
  add randomize set
  • Loading branch information
Baptouuuu committed Feb 29, 2020
2 parents 0255715 + 93ef56f commit 6f0ce12
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 4 deletions.
10 changes: 10 additions & 0 deletions README.md
Expand Up @@ -91,3 +91,13 @@ By default the library supports the shrinking of data to help you find the small
![](printer.png)

**Important**: shrinking use recursion to find the smallest value thus generating deep call stacks, so you may need to disable the xdebug `Maximum function nesting level` option.

## Configuration

### Set size

By default it will run 100 iterations of different values to test your properties. You can manually change this value in each test by calling `$this->forAll(/** $set */)->take($somethingOtherThan100)`.

Specifying a different value can be repetitive if you want all your tests to run the same number of iterations, with this in mind you can specify an [env variable](https://phpunit.readthedocs.io/en/8.5/configuration.html#the-env-element) named `BLACKBOX_SET_SIZE` in your `phpunit.xml.dist` set to the number of iterations you want for all your tests.

**Note**: of course you can override this value locally in each tests.
3 changes: 3 additions & 0 deletions phpunit.xml.dist
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>

<phpunit colors="true" bootstrap="vendor/autoload.php" printerClass="Innmind\BlackBox\PHPUnit\ResultPrinterV8">
<php>
<env name="BLACKBOX_SET_SIZE" value="200" />
</php>
<testsuites>
<testsuite name="Test suite">
<directory>./tests</directory>
Expand Down
9 changes: 8 additions & 1 deletion src/PHPUnit/BlackBox.php
Expand Up @@ -9,6 +9,13 @@ trait BlackBox
{
protected function forAll(Set $first, Set ...$sets): Scenario
{
return new Scenario($first, ...$sets);
$scenario = new Scenario($first, ...$sets);
$size = \getenv('BLACKBOX_SET_SIZE');

if ($size !== false) {
$scenario = $scenario->take((int) $size);
}

return $scenario;
}
}
12 changes: 11 additions & 1 deletion src/PHPUnit/Scenario.php
Expand Up @@ -6,11 +6,14 @@
use Innmind\BlackBox\{
Set,
Set\Composite,
Set\Randomize,
};

final class Scenario
{
private Set $set;
/** @var \Closure(Set): Set */
private \Closure $wrap;
private TestRunner $run;

public function __construct(Set $first , Set ...$sets)
Expand All @@ -31,13 +34,18 @@ public function __construct(Set $first , Set ...$sets)
}

$this->set = $set->take(100);
$this->wrap = \Closure::fromCallable(static fn(Set $set): Set => new Randomize($set));
$this->run = new TestRunner;
}

public function take(int $size): self
{
$wrap = $this->wrap;
$self = clone $this;
$self->set = $this->set->take($size);
$self->wrap = \Closure::fromCallable(
static fn(Set $set): Set => $wrap($set)->take($size),
);

return $self;
}
Expand All @@ -63,7 +71,9 @@ public function filter(callable $predicate): self

public function then(callable $test): void
{
foreach ($this->set->values() as $values) {
$set = ($this->wrap)($this->set);

foreach ($set->values() as $values) {
($this->run)($test, $values);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Set/Email.php
Expand Up @@ -21,7 +21,7 @@ static function(string $address, string $domain, string $tld): string {
Strings::matching('[a-zA-Z0-9][a-zA-Z0-9+\-\._]{1,62}[a-zA-Z0-9]')->filter(static function(string $string): bool {
return !\preg_match('~\.\.~', $string);
}),
Strings::matching('[a-zA-Z0-9][a-zA-Z0-9\-\.]{1,62}[a-zA-Z0-9]')->filter(static function(string $string): bool {
Strings::matching('[a-zA-Z0-9][a-zA-Z0-9\-\.]{1,61}[a-zA-Z0-9]')->filter(static function(string $string): bool {
return !\preg_match('~\.\.~', $string);
}),
Strings::matching('[a-zA-Z]{1,63}'),
Expand Down
43 changes: 43 additions & 0 deletions src/Set/Randomize.php
@@ -0,0 +1,43 @@
<?php
declare(strict_types = 1);

namespace Innmind\BlackBox\Set;

use Innmind\BlackBox\Set;

/**
* Use this set to prevent iterating over all possible combinations of a composite set
*
* It will allow to test more diverse combinations for a given set
*/
final class Randomize implements Set
{
private Set $set;
private int $size;

public function __construct(Set $set)
{
$this->set = $set;
$this->size = 100;
}

public function take(int $size): Set
{
$self = clone $this;
$self->size = $size;

return $self;
}

public function filter(callable $predicate): Set
{
return new self($this->set->filter($predicate));
}

public function values(): \Generator
{
for ($i = 0; $i < $this->size; $i++) {
yield $this->set->values()->current();
}
}
}
3 changes: 2 additions & 1 deletion tests/PHPUnit/BlackBoxTest.php
Expand Up @@ -29,6 +29,7 @@ public function assert(): int
}
};

$this->assertSame(100, $class->assert());
// 200 because it reads the `BLACKBOX_SET_SIZE` env var
$this->assertSame(200, $class->assert());
}
}
80 changes: 80 additions & 0 deletions tests/Set/RandomizeTest.php
@@ -0,0 +1,80 @@
<?php
declare(strict_types = 1);

namespace Tests\Innmind\BlackBox\Set;

use Innmind\BlackBox\{
Set\Randomize,
Set,
Set\Value,
};

class RandomizeTest extends TestCase
{
public function testInterface()
{
$this->assertInstanceOf(
Set::class,
new Randomize($this->createMock(Set::class)),
);
}

public function testGenerate100ValuesByDefault()
{
$set = new Randomize(
Set\Elements::of(new \stdClass, 42),
);

$this->assertCount(100, $this->unwrap($set->values()));
}

public function testTake()
{
$set1 = new Randomize(
Set\Elements::of(new \stdClass, 42),
);
$set2 = $set1->take(50);

$this->assertInstanceOf(Set::class, $set2);
$this->assertNotSame($set2, $set1);
$this->assertCount(100, $this->unwrap($set1->values()));
$this->assertCount(50, $this->unwrap($set2->values()));
}

public function testFilter()
{
$set1 = new Randomize(
Set\Elements::of('foo', 42),
);
$set2 = $set1->filter(fn($v) => \is_int($v));

$this->assertInstanceOf(Set::class, $set2);
$this->assertNotSame($set2, $set1);
$this->assertCount(100, $this->unwrap($set1->values()));
$this->assertCount(100, $this->unwrap($set2->values()));
$this->assertCount(
2,
\array_unique($this->unwrap($set1->values())),
);
$this->assertCount(
1,
\array_unique($this->unwrap($set2->values())),
);
}

public function testAlwaysTakeTheFirstValueGeneratedByTheUnderlyingSet()
{
$set = new Randomize(
$inner = $this->createMock(Set::class),
);
$expected = Value::immutable(new \stdClass);
$inner
->expects($this->exactly(100))
->method('values')
->willReturn((fn() => yield $expected)());

foreach ($set->values() as $value) {
$this->assertSame($expected, $value);
}
}
}

0 comments on commit 6f0ce12

Please sign in to comment.