rawr/phpunit-data-provider

Lightweight builder for PhpUnit data providers

Maintainers

👁 danon

Package info

github.com/t-regx/phpunit-data-provider

pkg:composer/rawr/phpunit-data-provider

Fund package maintenance!

danon

Statistics

Installs: 420 102

Dependents: 8

Suggesters: 0

Stars: 67

Open Issues: 3

3.3.1 2025-01-15 11:18 UTC

Requires

  • php: >=7.1.0

Requires (Dev)

Suggests

None

Provides

None

Conflicts

None

Replaces

None

MIT a8bbc37340cee2976265ec06fe1694f499233f67

This package is auto-updated.

Last update: 2026-06-15 14:13:26 UTC


README

👁 Image

Helper for PhpUnit @dataProvider

Handy require-dev testing tool for PhpUnit. It allows to manage data providers with zip(), join(), cross(), pairs(), slice(), map() and more.

👁 Build Status
👁 Coverage Status
👁 Dependencies
👁 License
👁 Composer lock

👁 PHP Version
👁 PHP Version
👁 PHP Version
👁 PHP Version
👁 PHP Version
👁 PHP Version
👁 PHP Version
👁 PHP Version
👁 PHP Version

👁 PRs Welcome

  1. Installation
  2. Overview
  3. Documentation
  4. Migration

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');
}

👁 list.png

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->blueColors(), $this->yellowColors(), $this->redColors());
}

public function blueColors(): DataProvider {
 return DataProvider::tuples(
 ['blue', 'sky'], 
 ['deep blue', 'ocean']
 );
}

public function yellowColors(): iterable {
 yield 'sun' => ['yellow', 'sun'];
}

public function redColors(): array {
 return [
 'apple' => ['red', 'apple']
 ];
}

👁 join.png

Note:

  • Only data provider with equal amounts of arguments in rows can be joined. DataProvider.drop() can be used to trim overflowing columns, or DataProvider::zip() to widen data provider with less rows.

DataProvider::zip()

Horizontally join data providers together.

💡 Useful for keeping data providers clean and simple.

/**
 * @test 
 * @dataProvider colors
 */
public function test($blueColor, $blueThing, $adjective, Factory $factory): void {
 // your test here
}

public function colors(): DataProvider {
 return DataProvider::zip($this->blueThings(), $this->adjectives(), $this->factories());
}

public function blueThings(): DataProvider {
 return DataProvider::tuples(
 ['blue', 'ink'],
 ['light blue', 'shirt'],
 ['deep blue', 'ocean']
 );
}

public function adjectives(): iterable {
 return DataProvider::list('liquid', 'comfortable', 'majestic');
}

public function factories(): iterable {
 yield [new InkFactory()];
 yield [new ShirtFactory()];
 yield [new OceanFactory()];
}

👁 zip.png

Note:

  • Only data provider with equal amounts of rows can be zipped. DataProvider.slice() can be used to trim overflowing rows, or DataProvider::join() to prolong a shorter data provider.

DataProvider::cross()

Creates a square matrix of given data providers.

💡 Useful for testing all combinations of arguments.

/**
 * @test 
 * @dataProvider colorsAndThings
 */
public function test(string $color, string $shade): void {
 // your test here
}

public function colorsAndThings(): DataProvider {
 return DataProvider::cross($this->colors(), $this->things());
}

public function colors(): array {
 return [
 ['blue'], ['yellow'], ['red']
 ];
}

public function things(): iterable {
 return DataProvider::list('sky', 'sun', 'apple');
}

👁 cross.png

DataProvider::pairs()

Calls test with two arguments. Each argument is paired with all of the other arguments. All rows are named according to the 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');
}

👁 pairs.png

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']
 ];
}

👁 of.png

Notes:

DataProvider::tuples()

Provide multiple arguments for each a test. DataProvider::tuples() 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::tuples(
 ['blue', 'sky'], 
 ['yellow', 'sun'],
 ['red', 'apple']
 );
}

👁 tuples.png

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 name 1' => 'blue',
 'custom name 2' => 'yellow',
 'custom name 3' => 'red'
 ]);
}

👁 dictionary.png

In most cases, DataProvider::list() or DataProvider::tuples() should be used to name rows based on arguments. Method DataProvider::dictionary() is useful when the arguments are not self-explanatory:

public function ports(): DataProvider {
 return DataProvider::dictionary([
 'http' => 80, 
 'https' => 443, 
 'ftp' => 21 
 ]);
}

DataProvider.map()

Transform each row's values in DataProvider to any other set of values.

💡 Useful for separating providers content and their form.

/**
* @test
* @dataProvider folderIterators
*/
public function test(\Iterator $iterator, string $name): void {
 // your test here
}

public function folderIterators(): DataProvider {
 return $this->folders()->map(function (string $name, string $path): array {
 return [
 new \DirectoryIterator($path),
 $name
 ];
 });
}

public function folders(): DataProvider {
 return DataProvider::tuples(
 ['temporary', '/tmp'],
 ['user directory', '/home'],
 ['system resources', '/usr/bin']);
}

👁 map.png

Notes:

  • Names in DataProvider will be preserved.

DataProvider.slice()

Remove leading or trailing rows from DataProvider.

💡 Useful for adapting DataProvider to be zipped or limit provided values.

/**
 * @test 
 * @dataProvider limitedColors
 */
public function test(string $color, string $thing): void {
 // your test here
}

public function limitedColors(): DataProvider {
 return $this->colors()->slice(0, 2); 
}

public function colors(): DataProvider {
 return DataProvider::tuples(
 ['blue', 'sky'], 
 ['yellow', 'sun'],
 ['red', 'apple']
 );
}

DataProvider.entries()

Provide two arguments for each a test, from key-value pairs. DataProvider::entries() names each row based on the key-value pair.

/**
 * @test 
 * @dataProvider colors
 */
public function test(string $color, string $thing): void {
 // your test here
}

public function colors(): DataProvider {
 return DataProvider::entries(
 'blue' => 'sky', 
 'yellow' => 'sun',
 'red' => 'apple',
 );
}

👁 entries.png

Documentation

Functionalities

Features

  • Clear naming
    • Each DataProvider builder sets proper names for rows, based on values.
  • Duplicate keys:
    • Duplicate keys are properly handled and formatted in an informative manner. No rows are ever being "lost" when editing.
  • Lazy evaluation:
    • Iterators are being evaluated only when called. Argument iterators are only called once, even if DataProvider is called multiple times.
  • DataProvider accepts many provider types.

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::tuples(
 ['blue', 'sky'], 
 ['yellow', 'sun'],
 ['red', 'apple']
 );
}

👁 names
👁 names

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, similar to:

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::tuples(['http', 80], ['https', 443], ['ssh', 22]));
}

Advanced usage

DataProvider can be combined with other DataProviders 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::tuples(
 ['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:

Notes

Notes on DataProvider::join():

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 providers
  • DataProvider::zip() can only zip data providers with the same amount of rows, otherwise IrregularDataProviderException is thrown. Additionally, each particular data provider must have the same amount of arguments in each row.
  • DataProvider::zip() accepts DataProvider or other iterable 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'), while DataProvider::distinctPairs() only makes pairs of different arguments.

Note on DataProvider::tuples():

  • DataProvider::tuples() is similar to DataProvider::of(), but ::of() accepts an explicit name, while DataProvider::tuples() titles the rows according to the values in the row.

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 to iterable or \TRegx\PhpUnit\DataProviders\DataProvider.
  • Removed \TRegx\DataProvider\CrossDataProviders::builder(), use \TRegx\PhpUnit\DataProviders\DataProvider::cross() instead.