Domain-based generators

Some default Generators target a particular business domain. They can be useful to test applications with plausible data instead of with universal values coming from a mathematical set like natural numbers or all the possible strings.

Names

Person names can be generated by selecting random elements from a dataset stored inside Eris source code.

<?php
use Eris\Generator;

class NamesTest extends PHPUnit_Framework_TestCase
{
    use Eris\TestTrait;

    public function testGeneratingNames()
    {
        $this->forAll(
            Generator\names()
        )->then(function ($name) {
            $this->assertInternalType('string', $name);
            var_dump($name);
        });
    }

    public function testSamplingShrinkingOfNames()
    {
        $generator = Generator\NamesGenerator::defaultDataSet();
        $sample = $this->sampleShrink($generator);
        $this->assertInternalType('array', $sample->collected());
        var_dump($sample->collected());
    }
}

testGeneratingNames shows a list of sample generated names. Their length increase with the size passed to Generators:

string(0) ""
string(0) ""
string(3) "Ita"
string(6) "Teresa"
string(8) "Raimunde"
string(7) "Laelius"
string(5) "Fanny"
string(6) "Aileen"
string(11) "Marie-Elise"
string(7) "Ignacio"
string(8) "Hendrick"

testSamplingShrinkingOfNames shows how names are shrinked to the slightly shorter name in the data set that is more similar to the current value:

array(8) {
  [0]=>
  string(9) "Gwenaelle"
  [1]=>
  string(8) "Ganaelle"
  [2]=>
  string(7) "Anaelle"
  [3]=>
  string(6) "Abelle"
  [4]=>
  string(5) "Abele"
  [5]=>
  string(4) "Abel"
  [6]=>
  string(3) "Abe"
  [7]=>
  string(2) "Di"
}

Dates

The date() Generator produces uniformly distributed DateTime objects.

<?php
use Eris\Generator;

class DateTest extends PHPUnit_Framework_TestCase
{
    use Eris\TestTrait;

    public function testYearOfADate()
    {
        $this->forAll(
            Generator\date("2014-01-01T00:00:00", "2014-12-31T23:59:59")
        )
            ->then(function (DateTime $date) {
                $this->assertEquals(
                    "2014",
                    $date->format('Y')
                );
            });
    }

    public function testDefaultValuesForTheInterval()
    {
        $this->forAll(
            Generator\date()
        )
            ->then(function (DateTime $date) {
                $this->assertGreaterThanOrEqual(
                    "1970",
                    $date->format('Y')
                );
                $this->assertLessThanOrEqual(
                    "2038",
                    $date->format('Y')
                );
            });
    }

    public function testFromDayOfYearFactoryMethodRespectsDistanceBetweenDays()
    {
        $this->forAll(
            Generator\choose(2000, 2020),
            Generator\choose(0, 364),
            Generator\choose(0, 364)
        )
        ->then(function ($year, $dayOfYear, $anotherDayOfYear) {
            $day = fromZeroBasedDayOfYear($year, $dayOfYear);
            $anotherDay = fromZeroBasedDayOfYear($year, $anotherDayOfYear);
            $this->assertEquals(
                abs($dayOfYear - $anotherDayOfYear) * 86400,
                abs($day->getTimestamp() - $anotherDay->getTimestamp()),
                "Days of the year $year: $dayOfYear, $anotherDayOfYear" . PHP_EOL
                . "{$day->format(DateTime::ISO8601)}, {$anotherDay->format(DateTime::ISO8601)}"
            );
        });
    }
}

function fromZeroBasedDayOfYear($year, $dayOfYear)
{
    return DateTime::createFromFormat(
        'z Y H i s',
        $dayOfYear . ' '. $year . ' 00 00 00',
        new DateTimeZone("UTC")
    );
}

testYearOfADate shows how to specify the lower and upper bound of an interval to pick dates from. These bounds are included in the interval.

testDefaultValuesForTheInterval shows that by default, given the 32-bit random generators used as a source, dates span the 1970-2038 interval of 32-bit UNIX timestamps.

testFromDayOfYearFactoryMethodRespectsDistanceBetweenDays uses the :ref:choose()<choose> Generator to pick directly integers and build DateTime objects itself. The test demonstrates a bug in the datetime PHP extension when an off-by-one error can be introduced when dealing with leap years.

Regex

The regex() Generator attempts to build a string matching the specified regular expression. It can be used to produce input strings much more close to a plausible format than totally random values.

<?php
use Eris\Generator;

class RegexTest extends \PHPUnit_Framework_TestCase
{
    use Eris\TestTrait;

    /**
     * Note that * and + modifiers are not supported. @see Generator\regex
     */
    public function testStringsMatchingAParticularRegex()
    {
        $this->forAll(
            Generator\regex("[a-z]{10}")
        )
            ->then(function ($string) {
                $this->assertEquals(10, strlen($string));
            });
    }
}

Here is a sample of generated values from testStringsMatchingAParticularRegex:

string(10) "ylunkcebou"
string(10) "whkjewwhud"
string(10) "pwirjzhbdw"
string(10) "dxsdwnsmyi"
string(10) "ttgczpimxs"
string(10) "jdsmlexlau"