phpunit和AppendIterator数据提供程序?

时间:2017-07-03 20:24:19

标签: php phpunit

A PHPUnit data provider allows the return of an iterator,但在使用AppendIterator时,仅使用附加的最后一个迭代器。我设置错了还是AppendIterators不能用作PHPUnit数据提供者?

测试文件:

<?php

use PHPUnit\Framework\TestCase;

class AppendIteratorTest extends TestCase
{
    /**
     * @dataProvider getAppendIterator
     */
    public function testAppendIterator($item) {
        echo PHP_EOL."test> $item".PHP_EOL;
    }

    public function getAppendIterator() {
        $iterator = new AppendIterator();
        $iterator->append(new ArrayIterator([[0], [1]]));
        $iterator->append(new ArrayIterator([[2], [3]]));
        $iterator->append(new ArrayIterator([[4], [5]]));

        foreach($iterator as $i) {
            echo 'foreach> '.print_r($i, true);
        }

        return $iterator;
    }
}

测试文件输出:

    $ vendor/bin/phpunit --debug AppendIteratorTest.php 
        foreach> Array
    (
        [0] => 0
    )
    foreach> Array
    (
        [0] => 1
    )
    foreach> Array
    (
        [0] => 2
    )
    foreach> Array
    (
        [0] => 3
    )
    foreach> Array
    (
        [0] => 4
    )
    foreach> Array
    (
        [0] => 5
    )
    PHPUnit 6.2.3 by Sebastian Bergmann and contributors.


    Starting test 'AppendIteratorTest::testAppendIterator with data set #0 (4)'.
    R
    test> 4

    Starting test 'AppendIteratorTest::testAppendIterator with data set #1 (5)'.
    R                                                                  2 / 2 (100%)
    test> 5


    Time: 24 ms, Memory: 4.00MB

    There were 2 risky tests:

    1) AppendIteratorTest::testAppendIterator with data set #0 (4)
    This test did not perform any assertions

    2) AppendIteratorTest::testAppendIterator with data set #1 (5)
    This test did not perform any assertions

    OK, but incomplete, skipped, or risky tests!
    Tests: 2, Assertions: 0, Risky: 2.

2 个答案:

答案 0 :(得分:0)

  

我设置错误还是AppendIterators不能用作PHPUnit数据提供者?

有点错误。 Phpunit中的数据提供者支持任何 Traversable AppendIterator Traversable Traversable 的)。所以它确实有效(你可以看到这一点,因为你没有得到错误)。

然而,数据提供者有一个(鲜为人知的)细节:每个数据集都可以有一个名称。如果 Iterator::key() 的值为ArrayIterator,则名称是提供的数组的键 - 或 - 。对于作为数组键的 $iterator->append(new ArrayIterator([0 => [0], 1 => [1]])); $iterator->append(new ArrayIterator([0 => [2], 1 => [3]])); $iterator->append(new ArrayIterator([0 => [4], 1 => [5]]));

这里你的密码代码可见,因为PHP会隐式创建它们:

    $iterator->append(new ArrayIterator([0 => [0], 1 => [1]]));
    $iterator->append(new ArrayIterator([2 => [2], 3 => [3]]));
    $iterator->append(new ArrayIterator([4 => [4], 5 => [5]]));

在你的键中,这些键总是0和1.因为你有重复的键,最后的键将“赢”。这是你看到的结果。

解释发生了什么。

然后可以是一个解决方案:

IndexingIterator

PHP中没有默认的Iterator可以重新为密钥编号,我在Iterator Garden public function getAppendIterator() { $iterator = new AppendIterator(); $iterator->append(new ArrayIterator([[0], [1]])); $iterator->append(new ArrayIterator([[2], [3]])); $iterator->append(new ArrayIterator([[4], [5]])); $index = 0; foreach ($iterator as $i) { yield $index++ => $i; } } 中没有密码,Börgers示例是向下,Nikic iter lib's reindex可以做到,...)你的案例中的快速内联将会产生重新索引:

$index

此处yield计数器用作Generator语句中的键。这会使您的数据提供者再次返回 Traversable ,这是 activeadmin 。然后Phpunit可以处理它。

当您有多个数据提供程序方法使用字符串键返回数据集时,问题类似。所有字符串键必须是唯一的,否则提供的数据将被重写。

这是内部的b / c,来自每个数据提供者的数据集明确地变成了一个数组。

我希望这可以回答您的问题并帮助您创建您正在寻找的数据提供者。

答案 1 :(得分:0)

使用foreach语法是有区别的。

(a)foreach ($iterator as $key => $value) { echo "$key = $value\n"; }

(b)foreach ($iterator as $value) { echo "$value\n"; }

在循环中使用键时,由于键值重复,将出现问题。因此,最后一个值获胜。在情况(b)中,当不使用密钥时,迭代将根据附加迭代器的顺序进行。请注意,在情况(b)中显示了所有值。

有一种方法可以从称为iterator_to_array的迭代器中提取所有值。此方法可以帮助您解决键重复的问题。它有一个附加参数,即不使用原始密钥。它将为每个值创建一个新的唯一数字索引。

示例$all_values = iterator_to_array($iterator, false);

我知道这是一个古老的话题,但是答案可能对其他用户有帮助。