11

我有一个测试方法依赖于另一种方法,该方法本身使用 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);
    }
}

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

4

3 回答 3

2

如果您的$resultintestCanDoSomeStuff()确实不是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的变量testcase 。如果它不存在,请对行为进行错误处理$resulttestCanDoSomeStuff()null

于 2012-07-24T11:28:32.233 回答
2

问题是几个因素的结果:

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

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

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

这是带有示例测试的代码。请注意,您不必命名数据行。如果您不使用'foo'密钥,请将 更改@dependstestOne-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 提交功能请求或拉取请求。

于 2012-07-24T18:46:43.920 回答
2

我还期望所描述的问题能够正常工作,经过一些研究,我发现这不是错误,而是预期的、未记录的行为。依赖测试不知道提供者返回的数据集,这就是测试参数为空的原因。

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

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

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

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

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

于 2013-06-25T17:33:13.890 回答