PHPUnit 和数据提供者的问题

发布于 2024-10-04 01:56:42 字数 892 浏览 0 评论 0原文

我有以下测试用例:

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

}

当我在 PHPUnit 中运行它时,我得到:

PHPUnit 3.4.14 by Sebastian Bergmann.

..........

Time: 0 seconds, Memory: 5.75Mb

OK (1 tests, 0 assertions)

测试应该失败,但事实并非如此。我尝试过:

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

但我得到:

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

我尝试将其声明为静态(如手册所述),但仍然没有区别。

我记得以前也以类似的方式工作过,但我可能是错的。我缺少什么?

预先感谢您的帮助。

PHP 5.3.3 上的 PHPUnit 3.4.14(取自 PEAR)

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一杆小烟枪 2024-10-11 01:56:42

小更新:从 3.2 版本(或附近的版本)开始,可以使用实例方法作为提供者。看看评论


提供者一定是这样的。

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

首先:如果您使用低于 3.3 的 phpunit 版本,该方法必须是静态

数组很重要。这并不难理解。对于应该调用测试的每次迭代,外部数组都有一个值。这里测试只被调用一次。内部数组是调用测试时使用的参数(按顺序)。您的测试只需要一个参数,因此内部数组始终需要一个值。另一个小例子

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

这里 testAdd 被执行了 3 次,每第二层 array 执行一次,它将接收来自内部 array 的值。您可能会注意到,测试将失败,并为您提供一条消息,其中数据集的迭代(此处为#3,因为 5+5 不是 6;))断言失败。

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.

冷了相思 2024-10-11 01:56:42

我遇到了同样的问题,当我删除自动生成的空构造函数时,它就解决了。我不确定为什么这可以解决问题。我也没有像类一样命名的测试方法。提供者方法不需要是静态的,到目前为止我的测试运行没有静态。但当我将提供者方法设置为静态时也会运行

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

怀念你的温柔 2024-10-11 01:56:42
<?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)
        );
    }
}

是完整的代码集

<?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

雨后彩虹 2024-10-11 01:56:42

我还发现您无法直接链接数据提供程序:

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

}

显然,PHPUnit 在运行任何测试之前调用所有提供程序函数,因此您甚至无法使用单独的提供程序函数将测试结果数据提供给其他测试。你能做的最好的事情就是模拟:

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

}

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

}
云裳 2024-10-11 01:56:42

从公共函数 testAddStream($logger) 中删除参数并重试。我不相信 PHPUnit 会调用需要它无法传递的参数的测试。

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.

世态炎凉 2024-10-11 01:56:42

看哪,我已经实现了一种模式来实现数据提供者的测试依赖关系!通过这种方式,您可以链接 dataProvider。

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

第二个数据集未通过 1 次测试来说明。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文