Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use @depends to depend on a test using an @dataProvider?

Tags:

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);
    }
}
?>
like image 718
Zsub Avatar asked May 22 '12 18:05

Zsub


People also ask

Which method is defined in a class that supplies a test method with data in DataProvider?

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'.

Can we pass parameters to DataProvider in TestNG?

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.

What is the use of DataProvider in TestNG?

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.

How do I use DataProvider in another class?

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.


2 Answers

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);
    }
}
like image 113
Majiy Avatar answered Sep 20 '22 16:09

Majiy


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.

like image 39
David Harkness Avatar answered Sep 22 '22 16:09

David Harkness