Skip to content

Commit

Permalink
extracting randomizer; added extensive percentage testing;
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleg Kulik committed Mar 22, 2018
1 parent 8ba30c3 commit 5485cde
Show file tree
Hide file tree
Showing 11 changed files with 156 additions and 25 deletions.
13 changes: 8 additions & 5 deletions src/Command/ApiSuiteCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use SlayerBirden\DFCodeGeneration\Generator\Tests\Get as TestGet;
use SlayerBirden\DFCodeGeneration\Generator\Tests\Gets as TestGets;
use SlayerBirden\DFCodeGeneration\Generator\Tests\IdRegistry;
use SlayerBirden\DFCodeGeneration\Generator\Tests\NullValuesRandomizer;
use SlayerBirden\DFCodeGeneration\Generator\Tests\ReflectionProviderFactory;
use SlayerBirden\DFCodeGeneration\Generator\Tests\Update as TestUpdate;
use SlayerBirden\DFCodeGeneration\Generator\Factory\SimpleProvider;
Expand Down Expand Up @@ -116,13 +117,15 @@ protected function execute(InputInterface $input, OutputInterface $output)
private function generateTests(): void
{
$entityProviderFactory = new ReflectionProviderFactory(new IdRegistry());
// 50% null values written by default
$randomizer = new NullValuesRandomizer(.5);

$files = [];
$files[] = (new TestAdd($this->entityClassName, $entityProviderFactory))->generate();
$files[] = (new TestDelete($this->entityClassName, $entityProviderFactory))->generate();
$files[] = (new TestGet($this->entityClassName, $entityProviderFactory))->generate();
$files[] = (new TestGets($this->entityClassName, $entityProviderFactory))->generate();
$files[] = (new TestUpdate($this->entityClassName, $entityProviderFactory))->generate();
$files[] = (new TestAdd($this->entityClassName, $entityProviderFactory, $randomizer))->generate();
$files[] = (new TestDelete($this->entityClassName, $entityProviderFactory, $randomizer))->generate();
$files[] = (new TestGet($this->entityClassName, $entityProviderFactory, $randomizer))->generate();
$files[] = (new TestGets($this->entityClassName, $entityProviderFactory, $randomizer))->generate();
$files[] = (new TestUpdate($this->entityClassName, $entityProviderFactory, $randomizer))->generate();

array_walk($files, function ($contents) {
$this->writer->write($contents);
Expand Down
12 changes: 5 additions & 7 deletions src/Generator/Tests/AbstractTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,18 @@ abstract class AbstractTest implements GeneratorInterface
private $innerProviders = [];
private $appended = [];
/**
* The default probability of Nulled values being filled with data
* @var float
* @var NullValuesRandomizer
*/
private $probabilityOfFilledNullable;
private $nullValuesRandomizer;

public function __construct(
string $entityClassName,
EntityProviderFactoryInterface $entityProviderFactory,
float $probabilityOfFilledNullable = .5
NullValuesRandomizer $nullValuesRandomizer
) {
$this->entityProviderFactory = $entityProviderFactory;
$this->entityClassName = $entityClassName;
$this->probabilityOfFilledNullable = $probabilityOfFilledNullable;
$this->nullValuesRandomizer = $nullValuesRandomizer;
}

protected function getLatestProvider()
Expand Down Expand Up @@ -87,8 +86,7 @@ private function getHaveInRepoPhrase(EntityProviderInterface $provider): string
$type = $item['type'];
$reference = $item['reference'] ?? [];
$nullable = $item['nullable'] ?? false;
// Skip 50% of nullable values (by default)
if ($nullable && rand(0,100)/100 > $this->probabilityOfFilledNullable) {
if ($nullable && !$this->nullValuesRandomizer->ifShouldWrite()) {
continue;
}
if ($reference) {
Expand Down
25 changes: 25 additions & 0 deletions src/Generator/Tests/NullValuesRandomizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace SlayerBirden\DFCodeGeneration\Generator\Tests;

class NullValuesRandomizer
{
/**
* @var float
*/
private $probabilityOfFilledNull;

public function __construct(float $probabilityOfFilledNull)
{
$this->probabilityOfFilledNull = $probabilityOfFilledNull;
}

/**
* @return bool
*/
public function ifShouldWrite(): bool
{
return rand(0,100)/100 < $this->probabilityOfFilledNull;
}
}
2 changes: 1 addition & 1 deletion tests/unit/Generator/Tests/AddTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function testCreateClass()
$this->provider->hasUnique()->willReturn(true);
$this->provider->getIdName()->willReturn('id');

$add = new Add('Dummy\\User', $this->factory->reveal());
$add = new Add('Dummy\\User', $this->factory->reveal(), new NullValuesRandomizer(.5));

$code = $add->generate();
$this->assertNotEmpty($code);
Expand Down
17 changes: 9 additions & 8 deletions tests/unit/Generator/Tests/BeforeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,8 @@ public function testManyToOne()

BODY;

$actual = (new class('Dummy\\User', $this->getFactory()) extends AbstractTest
$actual = (new class('Dummy\\User', $this->getFactory(), new NullValuesRandomizer(.5)) extends AbstractTest
{

public function generate(): string
{
return $this->generateHaveInRepo();
Expand Down Expand Up @@ -224,7 +223,7 @@ public function testManyToOneMultiple()

BODY;

$actual = (new class('Dummy\\User', $this->getFactory(), 2) extends AbstractTest
$actual = (new class('Dummy\\User', $this->getFactory(), new NullValuesRandomizer(.5), 2) extends AbstractTest
{
/**
* @var int
Expand All @@ -234,9 +233,10 @@ public function testManyToOneMultiple()
public function __construct(
string $entityClassName,
EntityProviderFactoryInterface $entityProviderFactory,
NullValuesRandomizer $randomizer,
int $times
) {
parent::__construct($entityClassName, $entityProviderFactory);
parent::__construct($entityClassName, $entityProviderFactory, $randomizer);
$this->times = $times;
}

Expand Down Expand Up @@ -319,7 +319,7 @@ public function testManyToManyMultiple()
]);
$this->providers[] = $provider4;

$actual = (new class('Dummy\\User', $this->getFactory(), 2) extends AbstractTest
$actual = (new class('Dummy\\User', $this->getFactory(), new NullValuesRandomizer(.5), 2) extends AbstractTest
{
/**
* @var int
Expand All @@ -329,9 +329,10 @@ public function testManyToManyMultiple()
public function __construct(
string $entityClassName,
EntityProviderFactoryInterface $entityProviderFactory,
NullValuesRandomizer $randomizer,
int $times
) {
parent::__construct($entityClassName, $entityProviderFactory);
parent::__construct($entityClassName, $entityProviderFactory, $randomizer);
$this->times = $times;
}

Expand Down Expand Up @@ -399,7 +400,7 @@ public function testRelationsNullable()
$provider1 = $this->providers[0];
$provider1->getEntitySpec()->willReturn($spec);

$actual = (new class('Dummy\\User', $this->getFactory(), .0) extends AbstractTest
$actual = (new class('Dummy\\User', $this->getFactory(), new NullValuesRandomizer(.0)) extends AbstractTest
{

public function generate(): string
Expand Down Expand Up @@ -454,7 +455,7 @@ public function testNullableColumn()
$provider1 = $this->providers[0];
$provider1->getEntitySpec()->willReturn($spec);

$actual = (new class('Dummy\\User', $this->getFactory(), .0) extends AbstractTest
$actual = (new class('Dummy\\User', $this->getFactory(), new NullValuesRandomizer(.0)) extends AbstractTest
{

public function generate(): string
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/Generator/Tests/DeleteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function testCreateClass()
$this->provider->hasUnique()->willReturn(true);
$this->provider->getIdName()->willReturn('id');

$delete = new Delete('Dummy\\User', $this->factory->reveal());
$delete = new Delete('Dummy\\User', $this->factory->reveal(), new NullValuesRandomizer(.5));

$code = $delete->generate();
$this->assertNotEmpty($code);
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/Generator/Tests/GetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function testCreateClass()
$this->provider->hasUnique()->willReturn(true);
$this->provider->getIdName()->willReturn('id');

$get = new Get('Dummy\\User', $this->factory->reveal());
$get = new Get('Dummy\\User', $this->factory->reveal(), new NullValuesRandomizer(.5));

$code = $get->generate();
$this->assertNotEmpty($code);
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/Generator/Tests/GetsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function testCreateClass()
$this->provider->hasUnique()->willReturn(true);
$this->provider->getIdName()->willReturn('id');

$gets = new Gets('Dummy\\User', $this->factory->reveal());
$gets = new Gets('Dummy\\User', $this->factory->reveal(), new NullValuesRandomizer(.5));
$code = $gets->generate();
$this->assertNotEmpty($code);

Expand Down
50 changes: 50 additions & 0 deletions tests/unit/Generator/Tests/NullValuesRandomizerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);

namespace SlayerBirden\DFCodeGeneration\Generator\Tests;

use PHPUnit\Framework\TestCase;

class NullValuesRandomizerTest extends TestCase
{
/**
* @dataProvider percentageProvider
*
* @param float $percentage
*/
public function testPercentage(float $percentage)
{
$randomizer = new NullValuesRandomizer($percentage);
$hits = 0;
$total = 1000000;
for ($i = 0; $i < $total; ++$i) {
$randomizer->ifShouldWrite() ? ++$hits : null;
}

$expected = (int)($percentage * 100);
$actual = round($hits / $total * 100);

$this->assertThat($actual, new RangeConstraint($expected - 1, $expected + 1));
}

public function testThatZeroNeverCalled()
{
$randomizer = new NullValuesRandomizer(.0);

$hits = 0;
for ($i = 0; $i < 1000000; ++$i) {
$randomizer->ifShouldWrite() ? ++$hits : null;
}

$this->assertSame(0, $hits);
}

public function percentageProvider(): array
{
return [
[.1],
[.5],
[.0],
];
}
}
54 changes: 54 additions & 0 deletions tests/unit/Generator/Tests/RangeConstraint.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);

namespace SlayerBirden\DFCodeGeneration\Generator\Tests;

use PHPUnit\Framework\Constraint\Constraint;

class RangeConstraint extends Constraint
{
/**
* @var int
*/
private $from;
/**
* @var int
*/
private $to;

public function __construct(int $from, int $to)
{
parent::__construct();
$this->from = $from;
$this->to = $to;
}

/**
* @inheritdoc
*/
public function toString(): string
{
return 'in range';
}

/**
* @inheritdoc
*/
protected function matches($other): bool
{
return $other >= $this->from && $other <= $this->to;
}

/**
* @inheritdoc
*/
protected function failureDescription($other): string
{
return \sprintf(
'%s is not in range between %s and %s',
$this->exporter->shortenedExport($other),
$this->from,
$this->to
);
}
}
2 changes: 1 addition & 1 deletion tests/unit/Generator/Tests/UpdateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public function testCreateClass()
$this->provider->hasUnique()->willReturn(true);
$this->provider->getIdName()->willReturn('id');

$update = new Update('Dummy\\User', $this->factory->reveal());
$update = new Update('Dummy\\User', $this->factory->reveal(), new NullValuesRandomizer(.5));

$code = $update->generate();
$this->assertNotEmpty($code);
Expand Down

0 comments on commit 5485cde

Please sign in to comment.