【问题标题】:Testing iterables in PHPUnit在 PHPUnit 中测试迭代
【发布时间】:2017-11-19 09:24:25
【问题描述】:

在 PHPUnit 中很容易断言两个数组包含相同的值:

 $this->assertEquals( [1, 2, 3], [1, 2, 3] );

最近的 PHP 版本使迭代器和生成器的使用更具吸引力,PHP 7.1 引入了the iterable pseudo-type。这意味着我可以编写函数来获取和返回iterable,而无需绑定到我使用普通的旧array 或使用懒惰的Generator

如何断言返回iterable 的函数的返回值?理想情况下,我可以做类似的事情

 $this->assertIterablesEqual( ['expected', 'values'], $iterable );

有这样的功能吗?或者,是否有一种不涉及在我的测试中添加一堆额外的命令式代码的理智测试方法?

【问题讨论】:

    标签: php arrays iterator phpunit php-7.1


    【解决方案1】:

    您可以使用iterator_to_array 函数,例如:

     $expected = [1, 2, 3];
     $this->assertEquals( $expected, iterator_to_array($iterable) );
    

    这也适用于generators

    希望有帮助

    【讨论】:

    • 如果你有一个Traversable 并且只关心值是的,那就可以了。但是它不适用于iterable,因为iterator_to_array 只需要Traversable
    【解决方案2】:

    我认为您需要先包装 Iterable。例如,Iterable 的装饰器可以在名为 ForeachIterator 的 Iterator Garden 中找到,即 decorating anything foreach-able 作为 Traversable

    $iterator = new ForeachIterator($iterable);
    $this->assertEquals( [1, 2, 3], iterator_to_array($iterator));
    

    注意细节,它还会在该测试中考虑对象Iterable,这对于正确的测试来说不够严格。

    但是,这应该很容易在您的测试中转换为私有辅助方法,以便仅将数组和可遍历对象(而不是不可遍历对象)转换为迭代器/数组并应用断言:

    private function assertIterablesEqual(array $expected, iterable $actual, $message = '')
    {
        $array = is_array($actual) ? $actual : iterator_to_array($actual);
        $this->assertEquals($expected, $array, $message);
    }
    

    这可以进一步extracted into an assertion class to extend Phpunit itself

    请注意,iterator_to_array 将用重复键替换条目,从而生成具有重复键的最后一次迭代值的数组。如果您还需要断言迭代键,则可能需要装饰或更改遍历方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-29
      • 2023-04-01
      • 2021-02-08
      • 2013-10-01
      相关资源
      最近更新 更多