diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php
index 75fec45..9e59ebe 100644
--- a/.php-cs-fixer.php
+++ b/.php-cs-fixer.php
@@ -26,7 +26,9 @@
$license->save();
-$config = PhpCsFixer\Config\Factory::fromRuleSet(new PhpCsFixer\Config\RuleSet\Php73($license->header()));
+$config = PhpCsFixer\Config\Factory::fromRuleSet(new PhpCsFixer\Config\RuleSet\Php73($license->header()), [
+ 'strict_comparison' => false,
+]);
$config->getFinder()
->exclude([
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 958b6fd..1c6c0dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## Unreleased
-For a full diff see [`1902cc2...main`][1902cc2...main].
+For a full diff see [`a5f2657...main`][a5f2657...main].
-[1902cc2...main]: https://github.com/ergebnis/data-provider/compare/1902cc2...main
+### Added
+
+* Imported data providers from [`ergebnis/test-util`](https://github.com/ergebnis/test-util) ([#1]), by [@localheinz]
+
+[a5f2657...main]: https://github.com/ergebnis/data-provider/compare/a5f2657...main
+
+[#1]: https://github.com/ergebnis/data-provider/pull/1
+
+[@localheinz]: https://github.com/localheinz
diff --git a/README.md b/README.md
index 6d0d225..08e97c9 100644
--- a/README.md
+++ b/README.md
@@ -21,8 +21,103 @@ composer require --dev ergebnis/data-provider
## Usage
-:bulb: This is a great place for showing a few usage examples!
+This package provides the following generic data providers:
+* [`Ergebnis\DataProvider\BoolProvider`](https://github.com/ergebnis/data-provider#dataproviderboolprovider)
+* [`Ergebnis\DataProvider\FloatProvider`](https://github.com/ergebnis/data-provider#dataproviderfloatprovider)
+* [`Ergebnis\DataProvider\IntProvider`](https://github.com/ergebnis/data-provider#dataproviderintprovider)
+* [`Ergebnis\DataProvider\NullProvider`](https://github.com/ergebnis/data-provider#dataprovidernullprovider)
+* [`Ergebnis\DataProvider\ObjectProvider`](https://github.com/ergebnis/data-provider#dataproviderobjectprovider)
+* [`Ergebnis\DataProvider\ResourceProvider`](https://github.com/ergebnis/data-provider#dataproviderresourceprovider)
+* [`Ergebnis\DataProvider\StringProvider`](https://github.com/ergebnis/data-provider#dataproviderstringprovider)
+
+Since it is possible to use multiple `@dataProvider` annotations for test methods, these generic data providers allow for reuse and composition of data providers:
+
+```php
+expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('Value can not be an empty or blank string.');
+
+ UserName::fromString($value);
+ }
+}
+```
+
+#### `DataProvider\BoolProvider`
+
+* `arbitrary()` provides `true`, `false`
+* `false()` provides `false`
+* `true()` provides `true`
+
+For examples, see [`Ergebnis\DataProvider\Test\Unit\BoolProviderTest`](test/Unit/BoolProviderTest.php).
+
+#### `DataProvider\FloatProvider`
+
+* `arbitrary()` provides arbitrary `float`s
+* `greaterThanOne()` provides `int`s greater than `1.0`
+* `greaterThanZero()` provides `int`s greater than `0.0`
+* `lessThanOne()` provides `int`s less than `1.0`
+* `lessThanZero()` provides `int`s less than `0.0`
+* `one()` provides `1.0`
+* `zero()` provides `0.0`
+
+For examples, see [`Ergebnis\DataProvider\Test\Unit\FloatProviderTest`](test/Unit/FloatProviderTest.php).
+
+#### `DataProvider\IntProvider`
+
+* `arbitrary()` provides arbitrary `int`s
+* `greaterThanOne()` provides `int`s greater than `1`
+* `greaterThanZero()` provides `int`s greater than `0`
+* `lessThanOne()` provides `int`s less than `1`
+* `lessThanZero()` provides `int`s less than `0`
+* `one()` provides `1`
+* `zero()` provides `0`
+
+For examples, see [`Ergebnis\DataProvider\Test\Unit\IntProviderTest`](test/Unit/IntProviderTest.php).
+
+#### `DataProvider\NullProvider`
+
+* `null()` provides `null`
+
+For examples, see [`Ergebnis\DataProvider\Test\Unit\NullProviderTest`](test/Unit/NullProviderTest.php).
+
+#### `DataProvider\ObjectProvider`
+
+* `object()` provides an instance of `stdClass`
+
+For examples, see [`Ergebnis\DataProvider\Test\Unit\ObjectProviderTest`](test/Unit/ObjectProviderTest.php).
+
+#### `DataProvider\ResourceProvider`
+
+* `resource()` provides a `resource`
+
+For examples, see [`Ergebnis\DataProvider\Test\Unit\ResourceProviderTest`](test/Unit/ResourceProviderTest.php).
+
+#### `DataProvider\StringProvider`
+
+* `arbitrary()` provides arbitrary `string`s
+* `blank()` provides `string`s consisting of whitespace characters only
+* `empty()` provides an empty `string`
+* `trimmed()` provides non-empty, non-blank `strings` without leading and trailing whitespace
+* `untrimmed()` provides non-empty, non-blank `string`s with additional leading and trailing whitespace
+* `withWhitespace()` provides non-empty, non-blank, trimmed `string`s containing whitespace
+
+For examples, see [`Ergebnis\DataProvider\Test\Unit\StringProviderTest`](test/Unit/StringProviderTest.php).
## Changelog
Please have a look at [`CHANGELOG.md`](CHANGELOG.md).
diff --git a/composer.json b/composer.json
index f550738..6f9369f 100644
--- a/composer.json
+++ b/composer.json
@@ -15,13 +15,13 @@
}
],
"require": {
- "php": "^7.3 || ^8.0"
+ "php": "^7.3 || ^8.0",
+ "fakerphp/faker": "^1.16.0"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.16.0",
"ergebnis/license": "^1.1.0",
"ergebnis/php-cs-fixer-config": "^3.2.1",
- "ergebnis/test-util": "^1.5.0",
"phpunit/phpunit": "~9.5.10",
"psalm/plugin-phpunit": "~0.16.1",
"vimeo/psalm": "^4.13.1"
diff --git a/composer.lock b/composer.lock
index 0de3c41..f2f48c6 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,189 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "af5dd83edafa2c6d7222301a5e814ee9",
- "packages": [],
+ "content-hash": "c95ce85293d4bbfd3f80094d7170a46a",
+ "packages": [
+ {
+ "name": "fakerphp/faker",
+ "version": "v1.16.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/FakerPHP/Faker.git",
+ "reference": "271d384d216e5e5c468a6b28feedf95d49f83b35"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/271d384d216e5e5c468a6b28feedf95d49f83b35",
+ "reference": "271d384d216e5e5c468a6b28feedf95d49f83b35",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0",
+ "psr/container": "^1.0 || ^2.0",
+ "symfony/deprecation-contracts": "^2.2"
+ },
+ "conflict": {
+ "fzaninotto/faker": "*"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.4.1",
+ "ext-intl": "*",
+ "symfony/phpunit-bridge": "^4.4 || ^5.2"
+ },
+ "suggest": {
+ "ext-curl": "Required by Faker\\Provider\\Image to download images.",
+ "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.",
+ "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.",
+ "ext-mbstring": "Required for multibyte Unicode string functionality."
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "v1.16-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Faker\\": "src/Faker/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "François Zaninotto"
+ }
+ ],
+ "description": "Faker is a PHP library that generates fake data for you.",
+ "keywords": [
+ "data",
+ "faker",
+ "fixtures"
+ ],
+ "support": {
+ "issues": "https://github.com/FakerPHP/Faker/issues",
+ "source": "https://github.com/FakerPHP/Faker/tree/v1.16.0"
+ },
+ "time": "2021-09-06T14:53:37+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
+ "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/container/issues",
+ "source": "https://github.com/php-fig/container/tree/1.1.1"
+ },
+ "time": "2021-03-05T17:36:06+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v2.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8",
+ "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.5-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-07-12T14:48:14+00:00"
+ }
+ ],
"packages-dev": [
{
"name": "amphp/amp",
@@ -649,83 +830,6 @@
],
"time": "2020-05-25T17:44:05+00:00"
},
- {
- "name": "ergebnis/classy",
- "version": "1.1.1",
- "source": {
- "type": "git",
- "url": "https://github.com/ergebnis/classy.git",
- "reference": "72840bda3ce8b7bdc9362e8646141eb3c5ca9947"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/ergebnis/classy/zipball/72840bda3ce8b7bdc9362e8646141eb3c5ca9947",
- "reference": "72840bda3ce8b7bdc9362e8646141eb3c5ca9947",
- "shasum": ""
- },
- "require": {
- "ext-tokenizer": "*",
- "php": "^7.2 || ^8.0"
- },
- "require-dev": {
- "ergebnis/composer-normalize": "^2.13.2",
- "ergebnis/license": "^1.1.0",
- "ergebnis/php-cs-fixer-config": "^2.13.0",
- "ergebnis/phpstan-rules": "~0.15.3",
- "ergebnis/test-util": "^1.0.0",
- "infection/infection": "~0.15.3",
- "phpstan/extension-installer": "^1.1.0",
- "phpstan/phpstan": "~0.12.70",
- "phpstan/phpstan-deprecation-rules": "~0.12.6",
- "phpstan/phpstan-strict-rules": "~0.12.9",
- "phpunit/phpunit": "^8.5.14",
- "psalm/plugin-phpunit": "~0.15.0",
- "vimeo/psalm": "^4.4.1",
- "zendframework/zend-file": "^2.8.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "1.0-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Ergebnis\\Classy\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Andreas Möller",
- "email": "am@localheinz.com"
- }
- ],
- "description": "Provides a finder for classy constructs (classes, interfaces, and traits).",
- "homepage": "https://github.com/ergebnis/classy",
- "keywords": [
- "classes",
- "classy",
- "constructs",
- "finder",
- "interfaces",
- "traits"
- ],
- "support": {
- "issues": "https://github.com/ergebnis/classy/issues",
- "source": "https://github.com/ergebnis/classy"
- },
- "funding": [
- {
- "url": "https://github.com/localheinz",
- "type": "github"
- }
- ],
- "time": "2021-02-01T08:25:30+00:00"
- },
{
"name": "ergebnis/composer-normalize",
"version": "2.16.0",
@@ -1072,147 +1176,6 @@
],
"time": "2021-11-15T21:44:59+00:00"
},
- {
- "name": "ergebnis/test-util",
- "version": "1.5.0",
- "source": {
- "type": "git",
- "url": "https://github.com/ergebnis/test-util.git",
- "reference": "7c85925bca8b2d2985eb7a208f53114dc64c780b"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/ergebnis/test-util/zipball/7c85925bca8b2d2985eb7a208f53114dc64c780b",
- "reference": "7c85925bca8b2d2985eb7a208f53114dc64c780b",
- "shasum": ""
- },
- "require": {
- "ergebnis/classy": "^1.1.1",
- "fakerphp/faker": "^1.14.1",
- "php": "^7.2 || ^8.0"
- },
- "require-dev": {
- "ergebnis/composer-normalize": "^2.13.3",
- "ergebnis/license": "^1.1.0",
- "ergebnis/php-cs-fixer-config": "^2.13.0",
- "ergebnis/phpstan-rules": "~0.15.3",
- "infection/infection": "~0.15.3",
- "phpstan/extension-installer": "^1.1.0",
- "phpstan/phpstan": "~0.12.65",
- "phpstan/phpstan-deprecation-rules": "~0.12.6",
- "phpstan/phpstan-phpunit": "~0.12.18",
- "phpstan/phpstan-strict-rules": "~0.12.9",
- "phpunit/phpunit": "^8.5.15",
- "psalm/plugin-phpunit": "~0.15.1",
- "vimeo/psalm": "^4.7.0"
- },
- "type": "library",
- "extra": {
- "composer-normalize": {
- "indent-size": 2,
- "indent-style": "space"
- }
- },
- "autoload": {
- "psr-4": {
- "Ergebnis\\Test\\Util\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Andreas Möller",
- "email": "am@localheinz.com"
- }
- ],
- "description": "Provides a helper trait and generic data providers for tests.",
- "homepage": "https://github.com/ergebnis/test-util",
- "keywords": [
- "assertion",
- "faker",
- "phpunit",
- "test"
- ],
- "support": {
- "issues": "https://github.com/ergebnis/test-util/issues",
- "source": "https://github.com/ergebnis/test-util"
- },
- "funding": [
- {
- "url": "https://github.com/localheinz",
- "type": "github"
- }
- ],
- "time": "2021-03-30T15:07:05+00:00"
- },
- {
- "name": "fakerphp/faker",
- "version": "v1.16.0",
- "source": {
- "type": "git",
- "url": "https://github.com/FakerPHP/Faker.git",
- "reference": "271d384d216e5e5c468a6b28feedf95d49f83b35"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/271d384d216e5e5c468a6b28feedf95d49f83b35",
- "reference": "271d384d216e5e5c468a6b28feedf95d49f83b35",
- "shasum": ""
- },
- "require": {
- "php": "^7.1 || ^8.0",
- "psr/container": "^1.0 || ^2.0",
- "symfony/deprecation-contracts": "^2.2"
- },
- "conflict": {
- "fzaninotto/faker": "*"
- },
- "require-dev": {
- "bamarni/composer-bin-plugin": "^1.4.1",
- "ext-intl": "*",
- "symfony/phpunit-bridge": "^4.4 || ^5.2"
- },
- "suggest": {
- "ext-curl": "Required by Faker\\Provider\\Image to download images.",
- "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.",
- "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.",
- "ext-mbstring": "Required for multibyte Unicode string functionality."
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "v1.16-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Faker\\": "src/Faker/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "François Zaninotto"
- }
- ],
- "description": "Faker is a PHP library that generates fake data for you.",
- "keywords": [
- "data",
- "faker",
- "fixtures"
- ],
- "support": {
- "issues": "https://github.com/FakerPHP/Faker/issues",
- "source": "https://github.com/FakerPHP/Faker/tree/v1.16.0"
- },
- "time": "2021-09-06T14:53:37+00:00"
- },
{
"name": "felixfbecker/advanced-json-rpc",
"version": "v3.2.1",
@@ -2672,54 +2635,6 @@
},
"time": "2016-08-06T20:24:11+00:00"
},
- {
- "name": "psr/container",
- "version": "1.1.1",
- "source": {
- "type": "git",
- "url": "https://github.com/php-fig/container.git",
- "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
- "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Psr\\Container\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "PHP-FIG",
- "homepage": "https://www.php-fig.org/"
- }
- ],
- "description": "Common Container Interface (PHP FIG PSR-11)",
- "homepage": "https://github.com/php-fig/container",
- "keywords": [
- "PSR-11",
- "container",
- "container-interface",
- "container-interop",
- "psr"
- ],
- "support": {
- "issues": "https://github.com/php-fig/container/issues",
- "source": "https://github.com/php-fig/container/tree/1.1.1"
- },
- "time": "2021-03-05T17:36:06+00:00"
- },
{
"name": "psr/event-dispatcher",
"version": "1.0.0",
@@ -3882,73 +3797,6 @@
],
"time": "2021-11-21T19:41:05+00:00"
},
- {
- "name": "symfony/deprecation-contracts",
- "version": "v2.5.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8",
- "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "2.5-dev"
- },
- "thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
- }
- },
- "autoload": {
- "files": [
- "function.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "A generic function and convention to trigger deprecation notices",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "time": "2021-07-12T14:48:14+00:00"
- },
{
"name": "symfony/event-dispatcher",
"version": "v5.3.11",
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index fcc3c81..9a8a401 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -1,2 +1,80 @@
-
+
+
+
+ $value
+
+
+
+
+ \Generator<string, array{0: bool}>
+ \Generator<string, array{0: bool}>
+ \Generator<string, array{0: bool}>
+
+
+
+
+ \Generator<string, array{0: float}>
+ \Generator<string, array{0: float}>
+ \Generator<string, array{0: float}>
+ \Generator<string, array{0: float}>
+ \Generator<string, array{0: float}>
+ \Generator<string, array{0: float}>
+ \Generator<string, array{0: float}>
+
+
+
+
+ \Generator<string, array{0: int}>
+ \Generator<string, array{0: int}>
+ \Generator<string, array{0: int}>
+ \Generator<string, array{0: int}>
+ \Generator<string, array{0: int}>
+ \Generator<string, array{0: int}>
+ \Generator<string, array{0: int}>
+
+
+
+
+ \Generator<string, array{0: null}>
+
+
+
+
+ \Generator<string, array{0: bool}>
+
+
+
+
+ \Generator<string, array{0: resource}>
+
+
+
+
+ \Generator<string, array{0: string}>
+ \Generator<string, array{0: string}>
+ \Generator<string, array{0: string}>
+ \Generator<string, array{0: string}>
+ \Generator<string, array{0: string}>
+ \Generator<string, array{0: string}>
+
+
+
+
+ $value
+
+
+ assertIsArray
+
+
+
+
+ $value
+
+
+
+
+ $value
+
+
+
diff --git a/src/AbstractProvider.php b/src/AbstractProvider.php
new file mode 100644
index 0000000..90eeadf
--- /dev/null
+++ b/src/AbstractProvider.php
@@ -0,0 +1,82 @@
+
+ */
+ static $fakers = [];
+
+ if (!\array_key_exists($locale, $fakers)) {
+ $faker = Factory::create($locale);
+
+ $faker->seed(9001);
+
+ $fakers[$locale] = $faker;
+ }
+
+ return $fakers[$locale];
+ }
+
+ /**
+ * @param array $values
+ *
+ * @throws Exception\EmptyValues
+ *
+ * @return \Generator
+ */
+ final protected static function provideDataForValues(array $values): \Generator
+ {
+ if ([] === $values) {
+ throw Exception\EmptyValues::create();
+ }
+
+ foreach ($values as $key => $value) {
+ yield $key => [
+ $value,
+ ];
+ }
+ }
+
+ /**
+ * @param array $values
+ *
+ * @throws Exception\EmptyValues
+ *
+ * @return \Generator
+ */
+ final protected static function provideDataForValuesWhere(array $values, \Closure $test): \Generator
+ {
+ if ([] === $values) {
+ throw Exception\EmptyValues::create();
+ }
+
+ $filtered = \array_filter($values, static function ($value) use ($test): bool {
+ return true === $test($value);
+ });
+
+ if ([] === $filtered) {
+ throw Exception\EmptyValues::filtered();
+ }
+
+ yield from self::provideDataForValues($filtered);
+ }
+}
diff --git a/src/BoolProvider.php b/src/BoolProvider.php
new file mode 100644
index 0000000..8dd244b
--- /dev/null
+++ b/src/BoolProvider.php
@@ -0,0 +1,56 @@
+
+ */
+ public static function arbitrary(): \Generator
+ {
+ yield from self::provideDataForValues(self::values());
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function false(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (bool $value): bool {
+ return false === $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function true(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (bool $value): bool {
+ return $value;
+ });
+ }
+
+ /**
+ * @return array
+ */
+ private static function values(): array
+ {
+ return [
+ 'bool-false' => false,
+ 'bool-true' => true,
+ ];
+ }
+}
diff --git a/src/Exception/EmptyValues.php b/src/Exception/EmptyValues.php
new file mode 100644
index 0000000..a43139d
--- /dev/null
+++ b/src/Exception/EmptyValues.php
@@ -0,0 +1,27 @@
+
+ */
+ public static function arbitrary(): \Generator
+ {
+ yield from self::provideDataForValues(self::values());
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function lessThanZero(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (float $value): bool {
+ return 0.0 > $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function zero(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (float $value): bool {
+ return 0.0 === $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function greaterThanZero(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (float $value): bool {
+ return 0.0 < $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function lessThanOne(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (float $value): bool {
+ return 1.0 > $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function one(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (float $value): bool {
+ return 1.0 === $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function greaterThanOne(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (float $value): bool {
+ return 1.0 < $value;
+ });
+ }
+
+ /**
+ * @return array
+ */
+ private static function values(): array
+ {
+ $faker = self::faker();
+
+ return [
+ 'float-less-than-minus-one' => -0.01 - $faker->randomFloat(null, 1),
+ 'float-minus-one' => -1.0,
+ 'float-zero' => 0.0,
+ 'float-plus-one' => 1.0,
+ 'float-greater-than-plus-one' => 0.01 + $faker->randomFloat(null, 1),
+ ];
+ }
+}
diff --git a/src/IntProvider.php b/src/IntProvider.php
new file mode 100644
index 0000000..4a05092
--- /dev/null
+++ b/src/IntProvider.php
@@ -0,0 +1,101 @@
+
+ */
+ public static function arbitrary(): \Generator
+ {
+ yield from self::provideDataForValues(self::values());
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function lessThanZero(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (int $value): bool {
+ return 0 > $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function zero(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (int $value): bool {
+ return 0 === $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function greaterThanZero(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (int $value): bool {
+ return 0 < $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function lessThanOne(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (int $value): bool {
+ return 1 > $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function one(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (int $value): bool {
+ return 1 === $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function greaterThanOne(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (int $value): bool {
+ return 1 < $value;
+ });
+ }
+
+ /**
+ * @return array
+ */
+ private static function values(): array
+ {
+ $faker = self::faker();
+
+ return [
+ 'int-less-than-minus-one' => -1 * $faker->numberBetween(1),
+ 'int-minus-one' => -1,
+ 'int-zero' => 0,
+ 'int-plus-one' => 1,
+ 'int-greater-than-plus-one' => $faker->numberBetween(1),
+ ];
+ }
+}
diff --git a/src/Example.php b/src/NullProvider.php
similarity index 51%
rename from src/Example.php
rename to src/NullProvider.php
index 1517c0a..10587c7 100644
--- a/src/Example.php
+++ b/src/NullProvider.php
@@ -13,22 +13,15 @@
namespace Ergebnis\DataProvider;
-final class Example
+final class NullProvider extends AbstractProvider
{
- private $name;
-
- private function __construct(string $name)
- {
- $this->name = $name;
- }
-
- public static function fromName(string $name): self
- {
- return new self($name);
- }
-
- public function name(): string
+ /**
+ * @return \Generator
+ */
+ public static function null(): \Generator
{
- return $this->name;
+ yield from self::provideDataForValues([
+ 'null' => null,
+ ]);
}
}
diff --git a/src/ObjectProvider.php b/src/ObjectProvider.php
new file mode 100644
index 0000000..9bb8b2e
--- /dev/null
+++ b/src/ObjectProvider.php
@@ -0,0 +1,27 @@
+
+ */
+ public static function object(): \Generator
+ {
+ yield from self::provideDataForValues([
+ 'object' => new \stdClass(),
+ ]);
+ }
+}
diff --git a/src/ResourceProvider.php b/src/ResourceProvider.php
new file mode 100644
index 0000000..eb7193c
--- /dev/null
+++ b/src/ResourceProvider.php
@@ -0,0 +1,27 @@
+
+ */
+ public static function resource(): \Generator
+ {
+ yield from self::provideDataForValues([
+ 'resource' => \fopen(__FILE__, 'rb'),
+ ]);
+ }
+}
diff --git a/src/StringProvider.php b/src/StringProvider.php
new file mode 100644
index 0000000..fb85eb8
--- /dev/null
+++ b/src/StringProvider.php
@@ -0,0 +1,173 @@
+
+ */
+ public static function arbitrary(): \Generator
+ {
+ yield from self::provideDataForValues(self::values());
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function blank(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (string $value): bool {
+ return '' === \trim($value)
+ && '' !== $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function empty(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (string $value): bool {
+ return '' === $value;
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function trimmed(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (string $value): bool {
+ return \trim($value) === $value
+ && '' !== \trim($value);
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function untrimmed(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (string $value): bool {
+ return \trim($value) !== $value
+ && '' !== \trim($value);
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ public static function withWhitespace(): \Generator
+ {
+ yield from self::provideDataForValuesWhere(self::values(), static function (string $value): bool {
+ return \trim($value) === $value
+ && 1 === \preg_match('/\s/', $value);
+ });
+ }
+
+ /**
+ * @return array
+ */
+ private static function values(): array
+ {
+ $faker = self::faker();
+
+ $arbitraryValues = [
+ 'string-arbitrary-sentence' => $faker->sentence(),
+ 'string-arbitrary-word' => $faker->word(),
+ ];
+
+ $whitespaceCharacters = self::whitespaceCharacters();
+
+ /** @var array $blankValues */
+ $blankValues = \array_combine(
+ \array_map(static function (string $key): string {
+ return \sprintf(
+ 'string-blank-%s',
+ $key,
+ );
+ }, \array_keys($whitespaceCharacters)),
+ $whitespaceCharacters,
+ );
+
+ $emptyValues = [
+ 'string-empty' => '',
+ ];
+
+ /** @var array $untrimmedValues */
+ $untrimmedValues = \array_combine(
+ \array_map(static function (string $key): string {
+ return \sprintf(
+ 'string-untrimmed-%s',
+ $key,
+ );
+ }, \array_keys($whitespaceCharacters)),
+ \array_map(static function (string $whitespaceCharacter) use ($faker): string {
+ return \sprintf(
+ '%s%s%s',
+ \str_repeat(
+ $whitespaceCharacter,
+ $faker->numberBetween(1, 5),
+ ),
+ $faker->word(),
+ \str_repeat(
+ $whitespaceCharacter,
+ $faker->numberBetween(1, 5),
+ ),
+ );
+ }, $whitespaceCharacters),
+ );
+
+ /** @var array $withWhitespaceValues */
+ $withWhitespaceValues = \array_combine(
+ \array_map(static function (string $key): string {
+ return \sprintf(
+ 'string-with-whitespace-%s',
+ $key,
+ );
+ }, \array_keys($whitespaceCharacters)),
+ \array_map(static function (string $whitespaceCharacter) use ($faker): string {
+ /** @var array $words */
+ $words = $faker->words($faker->numberBetween(2, 5));
+
+ return \implode(
+ $whitespaceCharacter,
+ $words,
+ );
+ }, $whitespaceCharacters),
+ );
+
+ return \array_merge(
+ $arbitraryValues,
+ $blankValues,
+ $emptyValues,
+ $untrimmedValues,
+ $withWhitespaceValues,
+ );
+ }
+
+ /**
+ * @return array
+ */
+ private static function whitespaceCharacters(): array
+ {
+ return [
+ 'carriage-return' => "\r",
+ 'line-feed' => "\n",
+ 'space' => ' ',
+ 'tab' => "\t",
+ ];
+ }
+}
diff --git a/test/Unit/AbstractProviderTestCase.php b/test/Unit/AbstractProviderTestCase.php
new file mode 100644
index 0000000..743ccea
--- /dev/null
+++ b/test/Unit/AbstractProviderTestCase.php
@@ -0,0 +1,118 @@
+ $values
+ * @param \Generator> $provider
+ */
+ final protected static function assertProvidesDataSetsForValues(array $values, \Generator $provider): void
+ {
+ self::assertExpectedValuesAreNotEmpty($values);
+
+ $expectedDataSets = \array_map(static function ($value): array {
+ return [
+ $value,
+ ];
+ }, $values);
+
+ $actualDataSets = \iterator_to_array($provider);
+
+ self::assertDataSetsAreNotEmpty($actualDataSets);
+
+ self::assertEquals(
+ $expectedDataSets,
+ $actualDataSets,
+ 'Failed asserting that a generator yields data sets for the expected values.',
+ );
+ }
+
+ /**
+ * @param array $specifications
+ * @param \Generator> $provider
+ */
+ final protected static function assertProvidesDataSetsForValuesSatisfyingSpecifications(array $specifications, \Generator $provider): void
+ {
+ self::assertContainsOnly(
+ 'string',
+ \array_keys($specifications),
+ true,
+ 'Failed asserting that the keys of specifications are all strings.',
+ );
+
+ self::assertContainsOnly(
+ Test\Util\Specification\Specification::class,
+ $specifications,
+ false,
+ \sprintf(
+ 'Failed asserting that the values of specifications implement "%s".',
+ Test\Util\Specification\Specification::class,
+ ),
+ );
+
+ $dataSets = \iterator_to_array($provider);
+
+ self::assertEquals(
+ \array_keys($specifications),
+ \array_keys($dataSets),
+ 'Failed asserting that the provided data has the same keys as the specifications.',
+ );
+
+ $keysForDataSetsWhereValueDoesNotSatisfySpecification = \array_filter(\array_keys($dataSets), static function (string $key) use ($dataSets, $specifications): bool {
+ $specification = $specifications[$key];
+
+ $dataSet = $dataSets[$key];
+
+ self::assertIsArray($dataSet, \sprintf(
+ 'Failed asserting that the data set provided for key "%s" is an array.',
+ $key,
+ ));
+
+ self::assertCount(1, $dataSet, \sprintf(
+ 'Failed asserting that the data set provided for key "%s" contains only one value.',
+ $key,
+ ));
+
+ $value = \array_shift($dataSet);
+
+ return !$specification->isSatisfiedBy($value);
+ });
+
+ self::assertEquals([], $keysForDataSetsWhereValueDoesNotSatisfySpecification, \sprintf(
+ 'Failed asserting that the value for the data sets with the keys "%s" satisfy the corresponding requirements.',
+ \implode(
+ '", "',
+ $keysForDataSetsWhereValueDoesNotSatisfySpecification,
+ ),
+ ));
+ }
+
+ final protected static function assertDataSetsAreNotEmpty(array $actual): void
+ {
+ self::assertNotEmpty($actual, 'Failed asserting that provided data sets are not empty.');
+ }
+
+ private static function assertExpectedValuesAreNotEmpty(array $values): void
+ {
+ self::assertNotEmpty($values, 'Failed asserting that expected values are not empty.');
+ }
+}
diff --git a/test/Unit/BoolProviderTest.php b/test/Unit/BoolProviderTest.php
new file mode 100644
index 0000000..b9f0799
--- /dev/null
+++ b/test/Unit/BoolProviderTest.php
@@ -0,0 +1,90 @@
+ Test\Util\Specification\Identical::create(false),
+ 'bool-true' => Test\Util\Specification\Identical::create(true),
+ ];
+
+ $provider = BoolProvider::arbitrary();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\BoolProvider::false()
+ *
+ * @param mixed $value
+ */
+ public function testFalseProvidesFalse($value): void
+ {
+ self::assertFalse($value);
+ }
+
+ public function testFalseReturnsGeneratorThatProvidesFalse(): void
+ {
+ $specifications = [
+ 'bool-false' => Test\Util\Specification\Identical::create(false),
+ ];
+
+ $provider = BoolProvider::false();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\BoolProvider::true()
+ *
+ * @param mixed $value
+ */
+ public function testTrueProvidesTrue($value): void
+ {
+ self::assertTrue($value);
+ }
+
+ public function testTrueReturnsGeneratorThatProvidesTrue(): void
+ {
+ $specifications = [
+ 'bool-true' => Test\Util\Specification\Identical::create(true),
+ ];
+
+ $provider = BoolProvider::true();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+}
diff --git a/test/Unit/ExampleTest.php b/test/Unit/ExampleTest.php
deleted file mode 100644
index 3034617..0000000
--- a/test/Unit/ExampleTest.php
+++ /dev/null
@@ -1,37 +0,0 @@
-sentence;
-
- $example = DataProvider\Example::fromName($name);
-
- self::assertSame($name, $example->name());
- }
-}
diff --git a/test/Unit/Exception/EmptyValuesTest.php b/test/Unit/Exception/EmptyValuesTest.php
new file mode 100644
index 0000000..4b79118
--- /dev/null
+++ b/test/Unit/Exception/EmptyValuesTest.php
@@ -0,0 +1,39 @@
+getMessage());
+ }
+
+ public function testFilteredReturnsException(): void
+ {
+ $exception = Exception\EmptyValues::filtered();
+
+ self::assertSame('Filtered values can not be empty.', $exception->getMessage());
+ }
+}
diff --git a/test/Unit/FloatProviderTest.php b/test/Unit/FloatProviderTest.php
new file mode 100644
index 0000000..01a2460
--- /dev/null
+++ b/test/Unit/FloatProviderTest.php
@@ -0,0 +1,173 @@
+ Test\Util\Specification\Closure::create(static function (float $value): bool {
+ return -1.0 > $value;
+ }),
+ 'float-minus-one' => Test\Util\Specification\Identical::create(-1.0),
+ 'float-zero' => Test\Util\Specification\Identical::create(0.0),
+ 'float-plus-one' => Test\Util\Specification\Identical::create(1.0),
+ 'float-greater-than-plus-one' => Test\Util\Specification\Closure::create(static function (float $value): bool {
+ return 1.0 < $value;
+ }),
+ ];
+
+ $provider = FloatProvider::arbitrary();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\FloatProvider::lessThanZero()
+ */
+ public function testLessThanZeroProvidesFloatLessThanZero(float $value): void
+ {
+ self::assertLessThan(0, $value);
+ }
+
+ public function testLessThanZeroReturnsGeneratorThatProvidesFloatLessThanZero(): void
+ {
+ $specifications = [
+ 'float-less-than-minus-one' => Test\Util\Specification\Closure::create(static function (float $value): bool {
+ return -1.0 > $value;
+ }),
+ 'float-minus-one' => Test\Util\Specification\Identical::create(-1.0),
+ ];
+
+ $provider = FloatProvider::lessThanZero();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\FloatProvider::zero()
+ */
+ public function testZeroProvidesZero(float $value): void
+ {
+ self::assertSame(0.0, $value);
+ }
+
+ public function testZeroReturnsGeneratorThatProvidesZero(): void
+ {
+ $specifications = [
+ 'float-zero' => Test\Util\Specification\Identical::create(0.0),
+ ];
+
+ $provider = FloatProvider::zero();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\FloatProvider::greaterThanZero()
+ */
+ public function testGreaterThanZeroProvidesFloatGreaterThanZero(float $value): void
+ {
+ self::assertGreaterThan(0.0, $value);
+ }
+
+ public function testGreaterThanZeroReturnsGeneratorThatProvidesFloatGreaterThanZero(): void
+ {
+ $specifications = [
+ 'float-plus-one' => Test\Util\Specification\Identical::create(1.0),
+ 'float-greater-than-plus-one' => Test\Util\Specification\Closure::create(static function (float $value): bool {
+ return 1.0 < $value;
+ }),
+ ];
+
+ $provider = FloatProvider::greaterThanZero();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\FloatProvider::lessThanOne()
+ */
+ public function testLessThanOneProvidesFloatLessThanOne(float $value): void
+ {
+ self::assertLessThan(1, $value);
+ }
+
+ public function testLessThanOneReturnsGeneratorThatProvidesFloatLessThanOne(): void
+ {
+ $specifications = [
+ 'float-less-than-minus-one' => Test\Util\Specification\Closure::create(static function (float $value): bool {
+ return -1.0 > $value;
+ }),
+ 'float-minus-one' => Test\Util\Specification\Identical::create(-1.0),
+ 'float-zero' => Test\Util\Specification\Identical::create(0.0),
+ ];
+
+ $provider = FloatProvider::lessThanOne();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ public function testOneReturnsGeneratorThatProvidesOne(): void
+ {
+ $specifications = [
+ 'float-plus-one' => Test\Util\Specification\Identical::create(1.0),
+ ];
+
+ $provider = FloatProvider::one();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\FloatProvider::greaterThanOne()
+ */
+ public function testGreaterThanOneProvidesFloatGreaterThanOne(float $value): void
+ {
+ self::assertGreaterThan(1, $value);
+ }
+
+ public function testGreaterThanOneReturnsGeneratorThatProvidesFloatGreaterThanOne(): void
+ {
+ $specifications = [
+ 'float-greater-than-plus-one' => Test\Util\Specification\Closure::create(static function (float $value): bool {
+ return 1.0 < $value;
+ }),
+ ];
+
+ $provider = FloatProvider::greaterThanOne();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+}
diff --git a/test/Unit/IntProviderTest.php b/test/Unit/IntProviderTest.php
new file mode 100644
index 0000000..8a46059
--- /dev/null
+++ b/test/Unit/IntProviderTest.php
@@ -0,0 +1,173 @@
+ Test\Util\Specification\Closure::create(static function (int $value): bool {
+ return -1 > $value;
+ }),
+ 'int-minus-one' => Test\Util\Specification\Identical::create(-1),
+ 'int-zero' => Test\Util\Specification\Identical::create(0),
+ 'int-plus-one' => Test\Util\Specification\Identical::create(1),
+ 'int-greater-than-plus-one' => Test\Util\Specification\Closure::create(static function (int $value): bool {
+ return 1 < $value;
+ }),
+ ];
+
+ $provider = IntProvider::arbitrary();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\IntProvider::lessThanZero()
+ */
+ public function testLessThanZeroProvidesIntLessThanZero(int $value): void
+ {
+ self::assertLessThan(0, $value);
+ }
+
+ public function testLessThanZeroReturnsGeneratorThatProvidesIntLessThanZero(): void
+ {
+ $specifications = [
+ 'int-less-than-minus-one' => Test\Util\Specification\Closure::create(static function (int $value): bool {
+ return -1 > $value;
+ }),
+ 'int-minus-one' => Test\Util\Specification\Identical::create(-1),
+ ];
+
+ $provider = IntProvider::lessThanZero();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\IntProvider::zero()
+ */
+ public function testZeroProvidesZero(int $value): void
+ {
+ self::assertSame(0, $value);
+ }
+
+ public function testZeroReturnsGeneratorThatProvidesZero(): void
+ {
+ $specifications = [
+ 'int-zero' => Test\Util\Specification\Identical::create(0),
+ ];
+
+ $provider = IntProvider::zero();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\IntProvider::greaterThanZero()
+ */
+ public function testGreaterThanZeroProvidesIntGreaterThanZero(int $value): void
+ {
+ self::assertGreaterThan(0, $value);
+ }
+
+ public function testGreaterThanZeroReturnsGeneratorThatProvidesIntGreaterThanZero(): void
+ {
+ $specifications = [
+ 'int-plus-one' => Test\Util\Specification\Identical::create(1),
+ 'int-greater-than-plus-one' => Test\Util\Specification\Closure::create(static function (int $value): bool {
+ return 1 < $value;
+ }),
+ ];
+
+ $provider = IntProvider::greaterThanZero();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\IntProvider::lessThanOne()
+ */
+ public function testLessThanOneProvidesIntLessThanOne(int $value): void
+ {
+ self::assertLessThan(1, $value);
+ }
+
+ public function testLessThanOneReturnsGeneratorThatProvidesIntLessThanOne(): void
+ {
+ $specifications = [
+ 'int-less-than-minus-one' => Test\Util\Specification\Closure::create(static function (int $value): bool {
+ return -1 > $value;
+ }),
+ 'int-minus-one' => Test\Util\Specification\Identical::create(-1),
+ 'int-zero' => Test\Util\Specification\Identical::create(0),
+ ];
+
+ $provider = IntProvider::lessThanOne();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ public function testOneReturnsGeneratorThatProvidesOne(): void
+ {
+ $specifications = [
+ 'int-plus-one' => Test\Util\Specification\Identical::create(1),
+ ];
+
+ $provider = IntProvider::one();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\IntProvider::greaterThanOne()
+ */
+ public function testGreaterThanOneProvidesIntGreaterThanOne(int $value): void
+ {
+ self::assertGreaterThan(1, $value);
+ }
+
+ public function testGreaterThanOneReturnsGeneratorThatProvidesIntGreaterThanOne(): void
+ {
+ $specifications = [
+ 'int-greater-than-plus-one' => Test\Util\Specification\Closure::create(static function (int $value): bool {
+ return 1 < $value;
+ }),
+ ];
+
+ $provider = IntProvider::greaterThanOne();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+}
diff --git a/test/Unit/NullProviderTest.php b/test/Unit/NullProviderTest.php
new file mode 100644
index 0000000..d1f5d4e
--- /dev/null
+++ b/test/Unit/NullProviderTest.php
@@ -0,0 +1,47 @@
+ Test\Util\Specification\Identical::create(null),
+ ];
+
+ $provider = NullProvider::null();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+}
diff --git a/test/Unit/ObjectProviderTest.php b/test/Unit/ObjectProviderTest.php
new file mode 100644
index 0000000..f4dc0a9
--- /dev/null
+++ b/test/Unit/ObjectProviderTest.php
@@ -0,0 +1,47 @@
+ Test\Util\Specification\Equal::create(new \stdClass()),
+ ];
+
+ $provider = ObjectProvider::object();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+}
diff --git a/test/Unit/ResourceProviderTest.php b/test/Unit/ResourceProviderTest.php
new file mode 100644
index 0000000..a0fabeb
--- /dev/null
+++ b/test/Unit/ResourceProviderTest.php
@@ -0,0 +1,49 @@
+ Test\Util\Specification\Closure::create(static function ($value): bool {
+ return \is_resource($value);
+ }),
+ ];
+
+ $provider = ResourceProvider::resource();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+}
diff --git a/test/Unit/StringProviderTest.php b/test/Unit/StringProviderTest.php
new file mode 100644
index 0000000..54a495f
--- /dev/null
+++ b/test/Unit/StringProviderTest.php
@@ -0,0 +1,178 @@
+ Test\Util\Specification\Closure::create(static function (string $value): bool {
+ return '' !== $value && '' !== \trim($value);
+ }),
+ 'string-arbitrary-word' => Test\Util\Specification\Closure::create(static function (string $value): bool {
+ return '' !== $value && '' !== \trim($value);
+ }),
+ 'string-blank-carriage-return' => Test\Util\Specification\Identical::create("\r"),
+ 'string-blank-line-feed' => Test\Util\Specification\Identical::create("\n"),
+ 'string-blank-space' => Test\Util\Specification\Identical::create(' '),
+ 'string-blank-tab' => Test\Util\Specification\Identical::create("\t"),
+ 'string-empty' => Test\Util\Specification\Identical::create(''),
+ 'string-untrimmed-carriage-return' => Test\Util\Specification\Pattern::create('/^\r{1,5}\w+\r{1,5}$/'),
+ 'string-untrimmed-line-feed' => Test\Util\Specification\Pattern::create('/^\n{1,5}\w+\n{1,5}$/'),
+ 'string-untrimmed-space' => Test\Util\Specification\Pattern::create('/^\s{1,5}\w+\s{1,5}$/'),
+ 'string-untrimmed-tab' => Test\Util\Specification\Pattern::create('/^\t{1,5}\w+\t{1,5}$/'),
+ 'string-with-whitespace-carriage-return' => Test\Util\Specification\Pattern::create('/^\w+(\r+\w+){1,4}$/'),
+ 'string-with-whitespace-line-feed' => Test\Util\Specification\Pattern::create('/^\w+(\n+\w+){1,4}$/'),
+ 'string-with-whitespace-space' => Test\Util\Specification\Pattern::create('/^\w+(\s+\w+){1,4}$/'),
+ 'string-with-whitespace-tab' => Test\Util\Specification\Pattern::create('/^\w+(\t+\w+){1,4}$/'),
+ ];
+
+ $provider = StringProvider::arbitrary();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\StringProvider::blank()
+ */
+ public function testBlankProvidesBlankString(string $value): void
+ {
+ self::assertSame('', \trim($value));
+ self::assertNotSame('', $value);
+ }
+
+ public function testBlankReturnsGeneratorThatProvidesStringsThatAreNeitherEmptyNorBlank(): void
+ {
+ $specifications = [
+ 'string-blank-carriage-return' => Test\Util\Specification\Identical::create("\r"),
+ 'string-blank-line-feed' => Test\Util\Specification\Identical::create("\n"),
+ 'string-blank-space' => Test\Util\Specification\Identical::create(' '),
+ 'string-blank-tab' => Test\Util\Specification\Identical::create("\t"),
+ ];
+
+ $provider = StringProvider::blank();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\StringProvider::empty()
+ */
+ public function testEmptyProvidesEmptyString(string $value): void
+ {
+ self::assertSame('', $value);
+ }
+
+ public function testEmptyReturnsGeneratorThatProvidesAnEmptyString(): void
+ {
+ $specifications = [
+ 'string-empty' => Test\Util\Specification\Identical::create(''),
+ ];
+
+ $provider = StringProvider::empty();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\StringProvider::untrimmed()
+ */
+ public function testUntrimmedProvidesUntrimmedString(string $value): void
+ {
+ self::assertNotSame(\trim($value), $value);
+ self::assertNotSame('', $value);
+ self::assertNotSame('', \trim($value));
+ }
+
+ /**
+ * @dataProvider \Ergebnis\DataProvider\StringProvider::trimmed()
+ *
+ * @param mixed $value
+ */
+ public function testTrimmedProvidesString($value): void
+ {
+ self::assertIsString($value);
+ }
+
+ public function testTrimmedReturnsGeneratorThatProvidesStringsThatAreTrimmed(): void
+ {
+ $specifications = [
+ 'string-arbitrary-sentence' => Test\Util\Specification\Closure::create(static function (string $value): bool {
+ return '' !== $value && '' !== \trim($value);
+ }),
+ 'string-arbitrary-word' => Test\Util\Specification\Closure::create(static function (string $value): bool {
+ return '' !== $value && '' !== \trim($value);
+ }),
+ 'string-with-whitespace-carriage-return' => Test\Util\Specification\Pattern::create('/^\w+(\r+\w+){1,4}$/'),
+ 'string-with-whitespace-line-feed' => Test\Util\Specification\Pattern::create('/^\w+(\n+\w+){1,4}$/'),
+ 'string-with-whitespace-space' => Test\Util\Specification\Pattern::create('/^\w+(\s+\w+){1,4}$/'),
+ 'string-with-whitespace-tab' => Test\Util\Specification\Pattern::create('/^\w+(\t+\w+){1,4}$/'),
+ ];
+
+ $provider = StringProvider::trimmed();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ public function testUntrimmedReturnsGeneratorThatProvidesUntrimmedStrings(): void
+ {
+ $specifications = [
+ 'string-untrimmed-carriage-return' => Test\Util\Specification\Pattern::create('/^\r{1,5}\w+\r{1,5}$/'),
+ 'string-untrimmed-line-feed' => Test\Util\Specification\Pattern::create('/^\n{1,5}\w+\n{1,5}$/'),
+ 'string-untrimmed-space' => Test\Util\Specification\Pattern::create('/^\s{1,5}\w+\s{1,5}$/'),
+ 'string-untrimmed-tab' => Test\Util\Specification\Pattern::create('/^\t{1,5}\w+\t{1,5}$/'),
+ ];
+
+ $provider = StringProvider::untrimmed();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+
+ public function testWithWhitespaceReturnsGeneratorThatProvidesTrimmedStringsWithWhitespace(): void
+ {
+ $specifications = [
+ 'string-arbitrary-sentence' => Test\Util\Specification\Closure::create(static function (string $value): bool {
+ return '' !== $value && '' !== \trim($value);
+ }),
+ 'string-with-whitespace-carriage-return' => Test\Util\Specification\Pattern::create('/^\w+(\r+\w+){1,4}$/'),
+ 'string-with-whitespace-line-feed' => Test\Util\Specification\Pattern::create('/^\w+(\n+\w+){1,4}$/'),
+ 'string-with-whitespace-space' => Test\Util\Specification\Pattern::create('/^\w+(\s+\w+){1,4}$/'),
+ 'string-with-whitespace-tab' => Test\Util\Specification\Pattern::create('/^\w+(\t+\w+){1,4}$/'),
+ ];
+
+ $provider = StringProvider::withWhitespace();
+
+ self::assertProvidesDataSetsForValuesSatisfyingSpecifications($specifications, $provider);
+ }
+}
diff --git a/test/Util/Specification/Closure.php b/test/Util/Specification/Closure.php
new file mode 100644
index 0000000..582a5b1
--- /dev/null
+++ b/test/Util/Specification/Closure.php
@@ -0,0 +1,53 @@
+closure = static function ($value) use ($closure): bool {
+ return true === $closure($value);
+ };
+ }
+
+ public static function create(\Closure $closure): self
+ {
+ return new self($closure);
+ }
+
+ public function isSatisfiedBy($value): bool
+ {
+ $closure = $this->closure;
+
+ $isSatisfiedBy = $closure($value);
+
+ if (!\is_bool($isSatisfiedBy)) {
+ throw new \RuntimeException(\sprintf(
+ 'Closure should return bool, got "%s" instead.',
+ \is_object($value) ? \get_class($value) : \gettype($value),
+ ));
+ }
+
+ return $isSatisfiedBy;
+ }
+}
diff --git a/test/Util/Specification/Equal.php b/test/Util/Specification/Equal.php
new file mode 100644
index 0000000..80ec14d
--- /dev/null
+++ b/test/Util/Specification/Equal.php
@@ -0,0 +1,43 @@
+value = $value;
+ }
+
+ /**
+ * @param mixed $value
+ */
+ public static function create($value): self
+ {
+ return new self($value);
+ }
+
+ public function isSatisfiedBy($value): bool
+ {
+ return $this->value == $value;
+ }
+}
diff --git a/test/Util/Specification/Identical.php b/test/Util/Specification/Identical.php
new file mode 100644
index 0000000..ec1dc02
--- /dev/null
+++ b/test/Util/Specification/Identical.php
@@ -0,0 +1,46 @@
+value = $value;
+ }
+
+ /**
+ * @param mixed $value
+ */
+ public static function create($value): self
+ {
+ return new self($value);
+ }
+
+ public function isSatisfiedBy($value): bool
+ {
+ return $this->value === $value;
+ }
+}
diff --git a/test/Util/Specification/Pattern.php b/test/Util/Specification/Pattern.php
new file mode 100644
index 0000000..7156f10
--- /dev/null
+++ b/test/Util/Specification/Pattern.php
@@ -0,0 +1,41 @@
+pattern = $pattern;
+ }
+
+ public static function create(string $pattern): self
+ {
+ return new self($pattern);
+ }
+
+ public function isSatisfiedBy($value): bool
+ {
+ if (!\is_string($value)) {
+ return false;
+ }
+
+ return 1 === \preg_match($this->pattern, $value);
+ }
+}
diff --git a/test/Util/Specification/Specification.php b/test/Util/Specification/Specification.php
new file mode 100644
index 0000000..0589cbd
--- /dev/null
+++ b/test/Util/Specification/Specification.php
@@ -0,0 +1,22 @@
+