# Scalar generators¶

## Integers¶

Integers can be generated, and by default they can be positive, or negative. You can force the sign of a number with:

• Generator\nat() which produces an integer >= 0.
• Generator\pos() which produces an integer > 0.
• Generator\neg() which produces an integer < 0.
• Generator\byte() which produces an integer >= 0 and <= 255.
<?php
use Eris\Generator;
use Eris\TestTrait;

class IntegerTest extends PHPUnit_Framework_TestCase
{
use TestTrait;

public function testSumIsCommutative()
{
$this->forAll( Generator\int(), Generator\int() ) ->then(function ($first, $second) {$x = $first +$second;
$y =$second + $first;$this->assertEquals(
$x,$y,
"Sum between {$first} and {$second} should be commutative"
);
});
}

public function testSumIsAssociative()
{
$this->forAll( Generator\int(), Generator\neg(), Generator\pos() ) ->then(function ($first, $second,$third) {
$x =$first + ($second +$third);
$y = ($first + $second) +$third;
$this->assertEquals($x,
$y, "Sum between {$first} and {$second} should be associative" ); }); } public function testByteData() {$this->forAll(
Generator\byte()
)
->then(function ($byte) {$this->assertTrue(
$byte >= 0 &&$byte <= 255,
"$byte is not a valid value for a byte" ); }); } }  For more precise and custom ranges, the Generator\choose() accepts a lower and upper bound for the interval to sample integers from. <?php use Eris\Generator; use Eris\TestTrait; class ChooseTest extends PHPUnit_Framework_TestCase { use TestTrait; public function testSumOfTwoIntegersFromBoundedRangesIsCommutative() {$this->forAll(
Generator\choose(-1000, 430),
Generator\choose(230, -30000)
)
->then(function ($first,$second) {
$x =$first + $second;$y = $second +$first;
$this->assertEquals($x,
$y, "Sum between {$first} and {$second} should be commutative" ); }); } }  ## Floats¶ Generator\float() will produce a float value, which can be positive or negative. In this example, testAPropertyHoldingOnlyForPositiveNumbers fails very quickly. <?php use Eris\Generator; class FloatTest extends \PHPUnit_Framework_TestCase { use Eris\TestTrait; public function testAPropertyHoldingForAllNumbers() {$this->forAll(Generator\float())
->then(function ($number) {$this->assertEquals(
0.0,
abs($number) - abs($number)
);
});
}

public function testAPropertyHoldingOnlyForPositiveNumbers()
{
$this->forAll(Generator\float()) ->then(function ($number) {
$this->assertTrue($number >= 0,
"$number is not a (loosely) positive number" ); }); } }  ## Booleans¶ Generator\bool() produces a boolean, chosen between true and false. It is mostly useful in conjunction with other Generators. <?php use Eris\Generator; use Eris\TestTrait; class BooleanTest extends PHPUnit_Framework_TestCase { use TestTrait; public function testBooleanValueIsTrueOrFalse() {$this->forAll(
Generator\bool()
)
->then(function ($boolValue) {$this->assertTrue(
($boolValue === true ||$boolValue === false),
"$boolValue is not true nor false" ); }); } }  ## Strings¶ Generator\string() produces a string of arbitrary length. Only printable characters can be included in the string, which is UTF-8. Currently only ASCII characters between 0x33 and 0x126 are used. <?php use Eris\Generator; use Eris\Listener; function string_concatenation($first, $second) { if (strlen($second) > 5) {
$second .= 'ERROR'; } return$first . $second; } class StringTest extends PHPUnit_Framework_TestCase { use Eris\TestTrait; public function testRightIdentityElement() {$this
->forAll(
Generator\string()
)
->then(function ($string) {$this->assertEquals(
$string, string_concatenation($string, ''),
"Concatenating '$string' to ''" ); }); } public function testLengthPreservation() {$this
->forAll(
Generator\string(),
Generator\string()
)
->hook(Listener\log(sys_get_temp_dir().'/eris-string-shrinking.log'))
->then(function ($first,$second) {
$result = string_concatenation($first, $second);$this->assertEquals(
strlen($first) + strlen($second),
strlen($result), "Concatenating '$first' to '$second' gives '$result'" . PHP_EOL
. var_export($first, true) . PHP_EOL . "strlen(): " . strlen($first) . PHP_EOL
. var_export($second, true) . PHP_EOL . "strlen(): " . strlen($second) . PHP_EOL
. var_export($result, true) . PHP_EOL . "strlen(): " . strlen($result) . PHP_EOL
. "First hex: " . var_export(bin2hex($first), true) . PHP_EOL . "Second hex: " . var_export(bin2hex($second), true) . PHP_EOL
. "Result hex: " . var_export(bin2hex($result), true) . PHP_EOL ); }); } }  See also For more complex use cases, try using a collection generator in conjunction with char(). ## Characters¶ Generator\char() generates a character from the chosen charset, by default with a utf-8 encoding. The only supported charset at the time of this writing is basic-latin. <?php use Eris\Generator; use Eris\Antecedent; class CharacterTest extends PHPUnit_Framework_TestCase { use Eris\TestTrait; public function testLengthOfAsciiCharactersInPhp() {$this->forAll(
Generator\char(['basic-latin'])
)
->then(function ($char) {$this->assertLenghtIs1($char); }); } public function testLengthOfPrintableAsciiCharacters() {$this->forAll(
Generator\char(['basic-latin'])
)
->when(Antecedent\printableCharacter())
->then(function ($char) {$this->assertFalse(ord($char) < 32); }); } public function testMultiplePrintableCharacters() {$this
->minimumEvaluationRatio(0.1)
->forAll(
Generator\char(['basic-latin']),
Generator\char(['basic-latin'])
)
->when(Antecedent\printableCharacters())
->then(function ($first,$second) {
$this->assertFalse(ord($first) < 32);
$this->assertFalse(ord($second) < 32);
});
}

/**
* @eris-ratio 10
*/
public function testMultiplePrintableCharactersFromAnnotation()
{
$this ->forAll( Generator\char(['basic-latin']), Generator\char(['basic-latin']) ) ->when(Antecedent\printableCharacters()) ->then(function ($first, $second) {$this->assertFalse(ord($first) < 32);$this->assertFalse(ord($second) < 32); }); } private function assertLenghtIs1($char)
{
$length = strlen($char);
$this->assertEquals( 1,$length,
"'$char' is too long:$length"
);
}
}


Generator\charPrintableAscii() can also be used to limit the range of the character to the set of printable characters, from 0x32 to 0x76.

## Constants¶

Generator\constant() produces always the same value, which is the value used to initialize it. This Generator is useful for debugging and simplifying composite Generators in these occasions.

Often, as shown in testUseConstantGeneratorImplicitly, constant are automatically boxed in this Generator if used where a Generator instance would be required:

<?php

use Eris\Generator;

class ConstantTest extends \PHPUnit_Framework_TestCase
{
use Eris\TestTrait;

public function testUseConstantGeneratorExplicitly()
{
$this ->forAll( Generator\nat(), Generator\constant(2) ) ->then(function ($number, $alwaysTwo) {$this->assertTrue(($number *$alwaysTwo % 2) === 0);
});
}

public function testUseConstantGeneratorImplicitly()
{
$this ->forAll( Generator\nat(), 2 ) ->then(function ($number, $alwaysTwo) {$this->assertTrue(($number *$alwaysTwo % 2) === 0);
});
}
}


## Elements¶

Generator\elements() produces a value randomly extracted from the specified array. Values can be specified as arguments or with a single, numeric array.

<?php
use Eris\Generator;

class ElementsTest extends \PHPUnit_Framework_TestCase
{
use Eris\TestTrait;

public function testElementsOnlyProducesElementsFromTheGivenArguments()
{
$this->forAll( Generator\elements(1, 2, 3) ) ->then(function ($number) {
$this->assertContains($number,
[1, 2, 3]
);
});
}

/**
* This means you cannot have a Elements Generator with a single element,
* which is perfectly fine as if you have a single element this generator
* is useless. Use Constant Generator instead
*/
public function testElementsOnlyProducesElementsFromTheGivenArrayDomain()
{
$this->forAll( Generator\elements([1, 2, 3]) ) ->then(function ($number) {
$this->assertContains($number,
[1, 2, 3]
);
});
}

public function testVectorOfElementsGenerators()
{
$this->forAll( Generator\vector( 4, Generator\elements([2, 4, 6, 8, 10, 12]) ) ) ->then(function ($vector) {
$sum = array_sum($vector);
$isEven = function ($number) {
return $number % 2 == 0; };$this->assertTrue(
$isEven($sum),
"$sum is not even, but it's the sum of the vector " . var_export($vector, true)
);
});
}
}


testVectorOfElementsGenerators shows how to compose the Elements Generator into a vector() to build a vector of selected, sometimes repeated, elements.

See also

oneOf() does the same with values instead of Generators.