Question

I have the following test case:

include_once('../Logger.php');

class LoggerTest extends PHPUnit_Framework_TestCase {

    public function providerLogger() {
        return new Logger;
    }

    /**
     * @dataProvider providerLogger
     */
    public function testAddStream($logger) {
        $this->assertTrue(false);
    }

}

When I run it in PHPUnit, I get:

PHPUnit 3.4.14 by Sebastian Bergmann.

..........

Time: 0 seconds, Memory: 5.75Mb

OK (1 tests, 0 assertions)

Test should fail, but it doesn't. I tried having:

public function providerLogger() {
    return array(new Logger);
}

But I get:

The data provider specified for LoggerTest::testAddStream is invalid.

I tried declaring it static (like the manual says), but still no difference.

I remember having it working in a similar fashion before, but I could be wrong. What am I missing?

Thanks in advance for your help.

PHPUnit 3.4.14 (taken from PEAR) on PHP 5.3.3

Was it helpful?

Solution

Minor update: It's OK to use instance methods as provider since version 3.2 (or somewhere around that). Have a look at the comments


The provider must look like this.

public static function providerLogger() {
    return array(
      array(new Logger)
    );
}

First of all: The method must be static if you are using phpunit version lower than 3.3 .

The array s are important. Its not that hard to understand. The outer array has one value for each iteration the test should get called. Here the test just get called once. The inner arrays are the parameters (in order) the test is invoked with. Your test expects exactly one parameter, so the inner arrays always needs exactly one value. Another little example

public static function addTestProvider () {
    return array(
        /* First + Second = third? */
        array(1,4,5),
        array(3,3,6),
        array(5,5,6)
    );
}
public function testAdd ($a, $b, $result) {
    $this->assertEquals($result, $a + $b);
}

Here testAdd gets executed 3 times, one for every second-level array, and it will receive the values from the inner array s. You may notice, that the test will fail and provides you a message in which iteration of the dataset (here #3, because 5+5 is not 6 ;)) the assertion failed.

OTHER TIPS

I had the same problem, and it was solved, when i deleted the empty constructor,that was auto generated. Iam not sure why this solves the problem. I also had no test method named like the class. The provider method doesnt need to be static, so far my test run without static. But also run when i make the provider method static

<?php

require_once 'calculator.php';

/**
 * Calculator test case.
 */
class CalculatorTest extends PHPUnit_Framework_TestCase {

    /**
     * @var Calculator
     */
    private $Calculator;

    /**
     * Prepares the environment before running a test.
     */
    protected function setUp() {
        parent::setUp ();
        // TODO Auto-generated CalculatorTest::setUp()
        $this->Calculator = new Calculator(/* parameters */);
    }

    /**
     * Cleans up the environment after running a test.
     */
    protected function tearDown() {
        // TODO Auto-generated CalculatorTest::tearDown()
        $this->Calculator = null;
        parent::tearDown ();
    }

    /**
     * Constructs the test case.
     */
    public function __construct() {
        // TODO Auto-generated constructor
    }

    /**
     * Tests Calculator->add()
     *
         * @dataProvider provider
         */
    public function testAdd($a, $b, $c) {
        // TODO Auto-generated CalculatorTest->testAdd()
        //$this->markTestIncomplete ( "add test not implemented" );

        //$this->Calculator->add(/* parameters */);
        $this->assertEquals($this->Calculator->add($a, $b), $c);
    }

    public static function provider()
    {
        return array(
          array(1, 1, 1),
          array(1, 1, -1),
          array(4, 2, 2),
          array(1, 1, 1)
        );
    }
}

is the complete set of code

I have also found that you cannot directly chain data providers:

class ProviderTest extends PHPUnit_Framework_TestCase {

    public function provider() {
        return array(array('test'));
    }

    /**
     * @dataProvider provider
     */
    public function providerTest1($test) {
        $this->assertTrue($test);
        return array(array($test));
    }

    /**
     * @dataProvider providerTest1
     */
    public function providerTest2($test) {
        $this->assertEquals('test', $test);
    }

}

Apparently, PHPUnit calls all the provider functions before running any tests, so you can't even use separate provider functions to feed test result data to other tests. The best you can do is to simulate:

class ProviderTest extends PHPUnit_Framework_TestCase {

    private $provider_data = array();

    public function provider() {
        return array(array('test'));
    }

    /**
     * @dataProvider provider
     */
    public function testProvider1($test) {
        $this->assertFalse(empty($test));
        array_push($this->provider_data, array($test));
    }

    /**
     * @depends testProvider1
     */
    public function testProvider2($test = NULL) {
        if(is_null($test)) {
            // simulate a provider
            foreach($this->provider_data as $row) {
                call_user_func_array(array($this, __METHOD__), $row);
            }
        } else {
            $this->assertEquals('test', $test);
        }
    }

}

Remove the parameter from public function testAddStream($logger) and try again. I don't believe PHPUnit will invoke a test which requires parameters it is unable to pass.

Behold I have achieved a pattern to achieve test dependencies for dataProviders! In this way you can chain dataProviders.

class ProviderDependencyTest extends PHPUnit_Framework_TestCase
{
    private static $dataSet;

    public function provideData()
    {
        self::$dataSet = array(
                    array(2,2,4),
                    array(1,0,2),
                    array(0,0,0)
                );

        //use static storage so you don't have to call the dataProvider again
        return self::$dataSet;
    }

    public function testProvideAdd()
    {
        $data = self::$dataSet;

        $this->assertEquals(3,count($data[0]));

        return $data[0];
    }

    /**
     * @depends testProvideAdd
     */
    public function testAdd($data)
    {
        $sum = $data[0] + $data[1];

        $this->assertEquals($data[2], $sum);

        return array($sum,$data[0],$data[1]);
    }

    /**
     * @depends testAdd
     */
    public function testSubtract($data)
    {
        $difference = $data[0] - $data[1];

        $this->assertEquals($data[2], $difference);

        return array($difference,$data[0],$data[1]);
    }

    /**
     * @depends testSubtract
     */
    public function testMultiply($data)
    {
        $product = $data[0] * $data[2];

        $this->assertEquals($data[1], $product);

        return $product;
    }

    /**
     * @depends testMultiply
     *
     * @dataProvider provideData
     */
    public function testMath($a,$b,$c)
    {
        //don't redo the first set of tests
        if(array($a,$b,$c) == self::$dataSet[0])
        {
            return;
        }

        $sum = $this->testAdd(array($a,$b,$c));
        $difference= $this->testSubtract($sum);
        $product = $this->testMultiply($difference);

        $this->assertInternalType('integer', $product);
    }
}

The 2nd data set fails 1 test to illustrate.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top