Logan Bailey

Adventures In Web Development

Blog, About, GitHub, and LinkedIn

Data providers are a powerful tool that allows the developer to reuse the same test with different input variables. To add a data provider, in your test case create a public that returns an array of arrays. The values of the inner arrays will be used as function parameters for your tests. In your test's docblock add the dataProvider annotation with the name of your function as seen below:

/**
 * @dataProvider simpleProvider
 */
public function testArraySum(array $input, int $sum)
{
	$this->assertEquals($sum, array_sum($input));
}

public function simpleProvider()
{
	return [
		[[1, 2, 3], 6],
		[[4, 5, 6], 15]
		[[2, 1], 4]
	];
}

This will run through each second level sub array in simpleProvider passing the elements of the array as function parameters to our test, testArraySum.

Naming

There are no hard rules when it comes to naming your data providers. However, ending your provider's method name with Provider makes it easy to identify data providers. It also helps you to think about what kind of values should belong in the provider, e.g.: in validDataProvider I'd expected to find data points that are valid. This might be useful when testing validation methods.

Named Data Sets

You can add names, array keys, to your array to help identify data sets:

public function responseProvider()
{
	return [
		'Ok' => [new Response(200)],
		'Not Found' => [new Response(404)]
	];
}

These keys will be logged when a test fails, which can make it easy to find the failing data set in a large provider.

  1. TestCase::testOkayReturnsTrueFor200LevelResponses with data set "Not Found" (Response) Failed asserting that false is true.

setUp Gotcha

setUp is run after the data provider is called. This means that you can't define properties in your setUp method and then use them in your data provider.

Overuse

Like all tools, it's possible that tests will arise that can be solved with a data provider but you may not want too. I've come up with a simple rule.

Only use data providers when the testing the same result.

Does X always result in Y. Does array_sum always result in the sum of the arrays? Passing in values which effect the assertions you run is a sign that you may not want a dataProvider. Take the following function:

public function canViewPost($user, $post) {
    if ($post->isAuthor($user) || $user->isAdmin() || $user->isEditor()) {
        return true;
    }

    return false;
}

I'd have a dataProvider for the test, testCanViewPostReturnsTrueForValidUsers and not use a data provider for testCanViewPostReturnsFalseForUsersWithOutPermission.

Posted In:
php phpunit