I have a testclass in which one test runs multiple times via a @dataProvider
and another test that @depends
on the first method. However, when I called var_dump
on what should be passed to the second test, it gives me a solid NULL
, which I didn't expect.
In other words: what should this do:
<?php
class DevicesTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider registerDataProvider
*/
public function testRegister($device, $supposedResult)
{
//do a bunch of tests
return array($device, $supposedResult);
}
public function registerDataProvider()
{
return array(array("foo", "foo"));
}
/**
* @depends testRegister
*/
public function testSaveDevicePreferences($deviceArr)
{
$this->assertNotEmpty($deviceArr);
}
}
?>
The execution of the test method is dependent upon the number of data sets defined by the @DataProvider annotated method. In the above example, testMethod() will be executed twice. The first time the values of parameter data will be 'data one' and the second time it will be 'data two'.
However, TestNG parameters enable us to pass the values only once per execution cycle. To overcome this, we can use DataProvider in TestNG that allows us to pass multiple parameters to a single test in a single execution. Using DataProviders, we can easily pass multiple values to a test in just one execution cycle.
Note: TestNG comes up with DataProvider to automate the process of providing test-cases for execution. DataProvider helps with data-driven test cases that carry the same methods but can be run multiple times with different data sets. It also helps in providing complex parameters to the test methods.
You can use the dataProviderClass attribute of @Test : public class StaticProvider { @DataProvider(name = "create") public static Object[][] createData() { return new Object[][] { new Object[] { new Integer(42) } }; } } public class MyTest { @Test(dataProvider = "create", dataProviderClass = StaticProvider.
In the current version of PHPUnit (5.4 as of today), it is possible.
According to the documentation:
When a test receives input from both a @dataProvider method and from one or more tests it @depends on, the arguments from the data provider will come before the ones from depended-upon tests. The arguments from depended-upon tests will be the same for each data set.
This is how it would look practically:
<?php
class DataProviderAndDependsCombinationTest extends AbstractUnittest{
public function dataProviderForSomething()
{
return array(
array(
'someProvidedValue',
'someOtherProvidedValue'
)
);
}
public function testToDependOn()
{
$this->assertTrue(true);
return 'someDependedValue';
}
/**
* @dataProvider dataProviderForSomething
* @depends testToDependOn
*/
public function testSomething($someProvidedValue, $someOtherProvidedValue, $someDependedValue)
{
$this->assertSame('someProvidedValue', $someProvidedValue);
$this->assertSame('someOtherProvidedValue', $someOtherProvidedValue);
$this->assertSame('someDependedValue', $someDependedValue);
}
}
Normally @dataProvider
is used when you want to run a test multiple times with different data sets for each. It exists to save you from writing looping code in the test and to allow different data sets to pass or fail individually.
As I said in my comments, I believe that PHPUnit will use either @depends
or @dataProvider
, and from your example my guess is that the second wins out. Another possibility is that tests with data providers cannot be used as dependencies because PHPUnit doesn't know which test-plus-dataset to pick.
Since registerDataProvider
returns a single data set, you could just as easily call it from the test itself. This would allow @depends
to work in the second test without the @dataProvider
. Assuming that testRegister
needs to modify $device
and/or $supposedResult
, this should work:
class DevicesTest extends PHPUnit_Framework_TestCase {
public function testRegister() {
list($device, $supposedResult) = $this->registerDataProvider();
//do a bunch of tests
//register a device in the DB
return array($device, $supposedResult);
}
public function registerDataProvider() {
return array("foo", "foo");
}
/**
* @depends testRegister
*/
public function testSaveDevicePreferences($data) {
list($device, $supposedResult) = $data;
// do stuff dependent on testRegister()
$this->assertEquals($device, $supposedResult);
}
}
If those variables don't need to be modified by the first test, you can simply call registerDataProvider
from both tests. Note that PHPUnit will not separate a returned array from a dependend upon test into arguments to the dependent test as the data provider mechanism does. This is because it doesn't know that the array being returned is multiple arguments versus a single argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With