rawr / cross-data-providers
Lightweight builder for PhpUnit data providers
Requires
- php: >=7.1.0
Requires (Dev)
- phpunit/phpunit: ^9.5.4 || ^8.0 || ^7.5
This package is auto-updated.
Last update: 2023-08-07 18:48:13 UTC
README
Helper for PhpUnit @dataProvider
Handy require-dev
testing tool for PhpUnit. It allows to manage data providers
with zip()
, join()
, cross()
, pairs()
, slice()
and more.
Installation
Installation for PHP 7.1 and later:
composer require --dev rawr/phpunit-data-provider
Overview
DataProvider
can be used to build, compose and edit data providers to be used with PhpUnit
by @sebastianbergmann.
DataProvider::list()
DataProvider::list()
provides a list of elements. Test is invoked each time with a single argument.
/** * @test * @dataProvider colors */ public function test(string $color): void { // your test here } public function colors(): DataProvider { return DataProvider::list("blue", "yellow", "red"); }
Additionally, DataProvider::list()
names rows based on values.
DataProvider::join()
Vertically join data providers together.
💡 Useful when two data providers are used in other tests, and a new test should use both of them.
/** * @test * @dataProvider colors */ public function test(string $color, string $thing): void { // your test here } public function colors(): DataProvider { return DataProvider::join($this->natureColors(), $this->shadeColors()); } public function natureColors(): DataProvider { return DataProvider::sets( ["blue", "sky"], ["yellow", "sun"], ["red", "apple"] ); } public function shadeColors(): array { return [ 'hair' => ["gray", "hair"], 'ink' => ["black", "ink"], 'dust' => ["lightgray", "dust"] ]; }
DataProvider::zip()
Horizontally join data providers together.
💡 Useful for keeping data providers clean and simple.
/** * @test * @dataProvider colors */ public function test($blueColor, $blueThing, $yellowThing, $redThing): void { // your test here } public function colors(): DataProvider { return DataProvider::zip($this->blueThings(), $this->yellowThings(), $this->redThings()); } public function blueThings(): DataProvider { return DataProvider::sets( ["blue", "pen"], ["light blue", "shirt"], ["deep blue", "ocean"] ); } public function yellowThings(): iterable { return DataProvider::list("sun", "apple", "lemon"); } public function redThings(): iterable { yield ["apple"]; yield ["cranberry"]; yield ["car"]; }
DataProvider::cross()
Creates a square matrix of given data providers.
💡 Useful for testing all combinations of arguments.
/** * @test * @dataProvider shadedColors */ public function test(string $shade, string $color): void { // your test here } public function shadedColors(): DataProvider { return DataProvider::cross($this->shades(), $this->colors()); } public function shades(): iterable { return DataProvider::list("light", "standard", "dark"); } public function colors(): array { return [ ["blue"], ["yellow"], ["red"] ]; }
DataProvider::pairs()
Calls test with two arguments. Each argument is paired with all of the other arguments.
Example shows a test paring image formats:
/** * @test * @dataProvider formats */ public function shouldConvertFile(string $from, string $to): void { // your test here } public function formats(): array { return DataProviders::distinctPairs('png', 'jpg', 'bmp'); }
DataProvider::of()
Instantiates a DataProvider
from a raw-array accepted by PhpUnit.
public function example(): DataProvider { return DataProvider::of($this->rawArray()); } public function rawArrayDataProvider(): array { return [ 'key' => ['argument 1', 'argument 2'] ]; }
DataProvider::sets()
Provide multiple arguments for each a test. DataProvider::sets()
names each row based on the values.
/** * @test * @dataProvider colors */ public function test(string color, string $thing): void { // your test here } public function colors(): DataProvider { return DataProvider::sets( ["blue", "sky"], ["yellow", "sun"], ["red", "apple"] ); }
DataProvider::dictionary()
Specify a single argument for test. DataProvider::dictionary()
names each row based on the provided array key.
/** * @test * @dataProvider colors */ public function test(string color): void { // your test here } public function colors(): DataProvider { return DataProvider::dictionary([ "custom key 1" => "blue", "custom key 2" => "yellow", "custom key 3" => "red" ]); }
In most cases, DataProvider::list()
should probably be used over DataProvider::dictionary()
. Method ::dictionary()
is useful when the arguments are not self-explanatory, for example:
public function ports(): DataProvider { return DataProvider::dictionary([ "http" => 80, "https" => 443, "ftp" => 21 ]); }
Documentation
Features
DataProvider
accepts many provider types.- each builder method sets proper names for rows, based on values
- properly handled duplicates in keys, formatting them in an informative manner
- lazily evaluates iterators, calling them only once (even if the provider is used multiple times)
Functionalities
Creating new data providers:
DataProvider::list()
,DataProvider::sets()
,DataProvider::dictionary()
,DataProvider::pairs()
,DataProvider::distinctPairs()
Composing existing providers:
DataProvider::zip()
,DataProvider::join()
,DataProvider::cross()
,DataProvider::of()
Editing existing providers:
DataProvider.slice()
,DataProvider.drop()
Names
DataProvider
sets proper names for each row based on values.
/** * @test * @dataProvider colors */ public function test(string color, string $thing): void { // your test here } public function colors(): DataProvider { return DataProvider::sets( ["blue", "sky"], ["yellow", "sun"], ["red", "apple"] ); }
Documentation
Example usage
DataProvider::cross()
returns an instance of DataProvider
which is a square matrix of input data providers.
/** * @test * @dataProvider services */ public function shouldLogin(string $service, string $method, int $port): void { // your test here } public function services(): DataProvider { return DataProvider::cross( [ ['github.com'], ['bitbucket.com'], ['gitlab.com'], ['sourceforge.net'] ], [ ['http', 80], ['https', 443], ['ssh', 22] ]); }
This is equivalent of having a regular data provider that is composed of 12 entries, that look like this:
public function services(): array { return [ ['github.com', 'http', 80], ['github.com', 'https', 443], ['github.com', 'ssh', 22], ['bitbucket.com', 'http', 80], ['bitbucket.com', 'https', 443], ['bitbucket.com', 'ssh', 22], ['gitlab.com', 'http', 80], ['gitlab.com', 'https', 443], ['gitlab.com', 'ssh', 22], ['sourceforge.net', 'http', 80], ['sourceforge.net', 'https', 443], ['sourceforge.net', 'ssh', 22], ]; }
DataProvider::cross()
accepts data providers of different
types: array
, \Iterator
, \IteratorAggregate
, \Traversable
, \Generator
,
iterable
and DataProvider
.
That means DataProvider
can be composed together.
public function services(): DataProvider { return DataProvider::cross( DataProvider::list('github.com', 'bitbucket.com', 'gitlab.com', 'sourceforge.net'), DataProvider::sets(['http', 80], ['https', 443], ['ssh', 22])); }
Advanced usage
DataProvider
can be combined with other DataProvider
s as well as regular PhpUnit data providers.
/** * @test * @dataProvider urls */ public function test0(string $url): void { // your test here } /** * @test * @dataProvider services */ public function test1(string $url, string $name, string $method, int $port): void { // your test here } /** * @test * @dataProvider allServices */ public function test2(string $url, string $name, string $method, int $port): void { // your test here } public function urls(): DataProvider { return DataProvider::list('github.com', 'bitbucket.com', 'gitlab.com', 'sourceforge.net'); } public function rawArrayProvider(): array { return [ ['GitHub'], ['BitBucket'], ['GitLab'], ['SourceForge'] ]; } public function services(): DataProvider { return DataProvider::cross( DataProvider::zip($this->urls(), $this->rawArrayProvider()), DataProvider::sets( ['http', 80], ['https', 443], ['ssh', 22])); } public function allServices(): DataProvider { return DataProvider::join( $this->services(), $this->localServices() ); } public function localServices(): array { return [ 'my local service' => ['localhost', 'local', 'http', '80'] ]; }
Accepted types
DataProvider
accepts any type of data provider:
- all types allowed
by PhpUnit:
array
,iterable
,\Traversable
,\Iterator
,\IteratorAggregate
,\Generator
DataProvider
itself
Notes
Notes on DataProvider::join()
:
DataProvider::join()
preserves names of each data provider, and also joins the names vertically. Duplicates in titles are preserved and presented appropriately.DataProvider::join()
accepts any type of data-provider.DataProvider::join()
is conceptually similar to calling\array_merge()
on raw-array providers, but\array_merge()
would override duplicate keys, whileDataProvider::join()
preserves duplicate keys, and titles them appropriately.DataProvider::join()
variadic arguments...iterable
and can be used to join many data providersDataProvider::join()
can only join data providers with the same amount of arguments in each row, otherwiseIrregularDataProviderException
is thrown.DataProvider::join()
acceptsDataProvider
or otheriterable
accepted by PhpUnit. If improper data-provider is passed,MalformedDataProviderException
is thrown.
Notes on DataProvider::zip()
:
DataProvider::zip()
preserves names of each data provider, and also joins them horizontally.DataProvider::zip()
accepts any type of data-provider.DataProvider::zip()
variadic arguments...iterable
and can zip many data providersDataProvider::zip()
can only zip data providers with the same amount of rows, otherwiseIrregularDataProviderException
is thrown. Additionally, each particular data provider must have the same amount of arguments in each row.DataProvider::zip()
acceptsDataProvider
or otheriterable
accepted by PhpUnit. If improper data-provider is passed,MalformedDataProviderException
is thrown.
Note on DataProvider::pairs()
:
DataProvider::pairs()
produces duplicate pairs (for example'png', 'png'
), whileDataProvider::distinctPairs()
only makes pairs of different arguments.
Note on DataProvider::sets()
:
DataProvider::sets()
is similar toDataProvider::of()
, but::of()
accepts an explicit name, whileDataProvider::sets()
titles the rows according to the values in the sets.
Migration from previous version
To use version 3.0.0
, migrating from 2.4.0
or earlier:
- Library namespace changed from
\TRegx\DataProvider\
to\TRegx\PhpUnit\DataProviders\
. - Change
\TRegx\DataProvider\DataProviders::cross()
to\TRegx\PhpUnit\DataProviders\DataProvider::cross()
. - Change
\TRegx\DataProvider\CrossDataProviders::cross()
to\TRegx\PhpUnit\DataProviders\DataProvider::cross()
. - Change your data providers return type from
array
toiterable
or\TRegx\PhpUnit\DataProviders\DataProvider
. - Removed
\TRegx\DataProvider\CrossDataProviders::builder()
, use\TRegx\PhpUnit\DataProviders\DataProvider::cross()
instead.