【问题标题】:Combining dependencies with data providers将依赖项与数据提供者相结合
【发布时间】:2012-07-24 11:09:03
【问题描述】:

我有一个测试方法依赖于另一种方法,该方法本身使用 PHPUnit 中的数据提供程序:

/** 
 * @dataProvider getFields
 */
public function testCanDoSomeStuff($parm1, $parm2) {
  $result = my_func($parm1, $parm2);
  $this->assertNotNull($result);

  return $result;
}

/**
 * @depends testCanDoSomeStuff
 */
public function testCanDoSomeMoreStuff($result) {
  $this->assertNotNull($result);
}

我还有一个getFields()数据提供函数,这里不用展示了。

依赖于数据提供者的第一个测试通过 - $result 不为空。

我希望测试的结果将作为$result 参数传递给依赖测试。但是testCanDoSomeMoreStuff函数接收到NULL参数,测试失败。

更新

这个简单的测试用例说明了问题:

class MyTest extends PHPUnit_Framework_TestCase {

    /**
     * @dataProvider myFunc
     */
    public function testCanDoSomeStuff($value) {
        $this->assertNotNull($value);
        return $value;
    }

    /**
     * @depends testCanDoSomeStuff
     */
    public function testCanDoSomeMoreStuff($value) {
        $this->assertNotNull($value);
    }

    /**
     * Data provider function
     */
    public function myFunc() {
      $values = array('22');
      return array($values);
    }
}

作为目前的解决方法,我将结果存储在测试之间的静态属性中。

【问题讨论】:

  • 您是否尝试过print_r($results); 来查看传递给testCanDoSomeMoreStuff() 的内容?
  • 嗨 Uzyn,是的 - 正在传递 null。我还打印了对“my_func”的调用结果,它不为空。
  • 您的代码在我看来没问题。也许您可能想分享您的实际代码,实际代码中可能存在一些错误。
  • 感谢 Uzyn;不幸的是,我不允许发布实际代码。

标签: php phpunit


【解决方案1】:

这个问题是由几个因素造成的:

  • 每个测试结果都存储在一个数组中,使用测试的名称作为键。
  • 接收数据的测试名称是<name> with data set #<x>
  • @depends 注释不接受多个单词。

有一个 hacky 解决方法:覆盖 TestCase::getDataSetAsString 以返回注释将接受的名称。由于所需的 TestCase 字段是私有的,因此这会产生一些问题,但是使用 PHP 5.3.2+ 您可以解决这个问题。

重要提示:很遗憾,您不能为每个数据行运行相关测试——只能对一个特定行进行。如果您的数据提供者只返回一行数据,这不是问题。

这是带有示例测试的代码。请注意,您不必命名数据行。如果您不使用 'foo' 键,请将 @depends 更改为 testOne-0

class DependencyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider data
     */
    public function testOne($x, $y) {
        return $x + $y;
    }

    public function data() {
        return array(
            'foo' => array(1, 2),
        );
    }

    /**
     * @depends testOne-foo
     */
    public function testTwo($z) {
        self::assertEquals(3, $z);
    }

    protected function getDataSetAsString($includeData = false) {
        if (!$includeData && $this->getPrivateField('data')) {
            return '-' . $this->getPrivateField('dataName');
        }
        return parent::getDataSetAsString($includeData);
    }

    private function getPrivateField($name) {
        $reflector = new ReflectionProperty('PHPUnit_Framework_TestCase', $name);
        $reflector->setAccessible(true);
        return $reflector->getValue($this);
    }
}

显然,这不是一个长期的解决方案。对于接收数据的方法的每个测试结果,您最好运行一次相关测试。您可以向 PHPUnit 提交功能请求或拉取请求。

【讨论】:

  • 谢谢大卫,这非常有用。我昨天在 github 上报告了这个问题以及示例代码,所以我想我现在先把它留给他们。
【解决方案2】:

如果你在testCanDoSomeStuff() 中的$result 真的不是null,那么这个应该工作。

要将其分开,首先尝试在没有数据提供者的情况下对其进行简化,如下所示:

class StackTest extends PHPUnit_Framework_TestCase {
    public function testCanDoSomeStuff() {
        $result = true;
        $this->assertTrue($result); 
        return $result;
    }

    /**
     * @depends testCanDoSomeStuff
     */
    public function testCanDoSomeMoreStuff($result) {
        $this->assertNotNull($result);
    }
}

对此进行测试应该会产生类似...

~>phpunit test.php
PHPUnit 3.6.11 by Sebastian Bergmann.
..
Time: 1 second, Memory: 3.25Mb
OK (2 tests, 2 assertions)

现在添加数据提供者,用你的函数替换我的简单变量,然后再次测试。

如果这个结果不同,var_dump 变量$result,然后在测试用例testCanDoSomeStuff() 中返回它。如果那里不是nullbug the behaviour

【讨论】:

  • 嗨,比约恩。抱歉,我应该补充一点,这正是我也尝试过的,并且有效。感谢您提供链接,我将尝试在可以作为错误报告的一部分提交的类中重新创建问题。
【解决方案3】:

我还预计所描述的问题会起作用,经过一些研究,我发现这不是错误,而是预期的、未记录的行为。依赖测试不知道提供者返回的数据集,所以测试参数为空。

来源:https://github.com/sebastianbergmann/phpunit/issues/183#issuecomment-816066

@dataProvider 注释在测试执行之前计算。基本上,预测试阶段为数据提供者提供的每组参数创建一个测试方法。 @depends 依赖于本质上是数据驱动测试的原型,因此在某种程度上,@depends 依赖于不存在的(未执行的测试)。

另一种思考方式是,如果提供者提供了一组以上的参数。 PHPUnit 会创建那么多 testDataProvider 方法,但不会有那么多 testDataReceiver 方法,因为在预测试阶段该测试方法上没有 @dataProvider 方法。

但是,您可以在同一测试方法上使用 @depends 和 @dataProvider。请注意确保参数顺序正确,尽管在这种情况下可能没有第一个参数。

基本上,当数据集有多行时,您应该使用数据提供程序。但是,您始终可以同时使用@depend@dataProvider 来实现大致相同的行为。

【讨论】:

    猜你喜欢
    • 2018-07-03
    • 2021-09-23
    • 2019-06-07
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多