【问题标题】:How to skip tests on error in PHPUnit?如何跳过 PHPUnit 中的错误测试?
【发布时间】:2016-08-24 18:08:16
【问题描述】:

当依赖的数据集有错误时,如何让 PHPUnit 跳过测试?


作品

如果我的数据提供者只有导致错误的东西,那么它将适当地跳过相关测试。 注意Skipped: 1

class DataProviderDependsTest extends PHPUnit_Framework_TestCase
{
    public function getDataProvider(){
      return [
        ['non-existent_file.txt'],
      ];
    }

    /**
     *  @dataProvider getDataProvider
     */
    public function testCanBeDependedOn($data){
      $actual = file_get_contents($data);
      $this->assertSame('expected',$actual);
    }

    /**
     *  @dataProvider getDataProvider
     *  @depends testCanBeDependedOn
     */
    public function testCanDepend($data){
      $this->assertTrue(false);
    }
}
PHPUnit 5.5.0 by Sebastian Bergmann and contributors.

ES                                                                  2 / 2 (100%)

Time: 28 ms, Memory: 4.00MB

There was 1 error:

1) DataProviderDependsTest::testCanBeDependedOn with data set #0 ('non-existent_file.txt')
file_get_contents(non-existent_file.txt): failed to open stream: No such file or directory

/home/xenial/phpunittest/test.php:16

ERRORS!
Tests: 1, Assertions: 0, Errors: 1, Skipped: 1.

不工作

但是,如果我向提供程序添加一个好的数据,那么尽管其余部分导致错误,PHPUnit 仍会继续执行 所有 依赖测试(甚至相应的有错误的数据集)。它不会跳过任何东西。 注意已将['real_file.txt'], 添加到数据提供者。

class DataProviderDependsTest extends PHPUnit_Framework_TestCase
{
    public function getDataProvider(){
      return [
        ['real_file.txt'],
        ['non-existent_file.txt'],
      ];
    }

    /**
     *  @dataProvider getDataProvider
     */
    public function testCanBeDependedOn($data){
      $actual = file_get_contents($data);
      $this->assertSame('expected',$actual);
    }

    /**
     *  @dataProvider getDataProvider
     *  @depends testCanBeDependedOn
     */
    public function testCanDepend($data){
      $this->assertTrue(false);
    }
}
PHPUnit 5.5.0 by Sebastian Bergmann and contributors.

.EFF                                                                4 / 4 (100%)

Time: 19 ms, Memory: 4.00MB

There was 1 error:

1) DataProviderDependsTest::testCanBeDependedOn with data set #1 ('non-existent_file.txt')
file_get_contents(non-existent_file.txt): failed to open stream: No such file or directory

/home/xenial/phpunittest/test.php:16

--

There were 2 failures:

1) DataProviderDependsTest::testCanDepend with data set #0 ('real_file.txt')
Failed asserting that false is true.

/home/xenial/phpunittest/test.php:25

2) DataProviderDependsTest::testCanDepend with data set #1 ('non-existent_file.txt')
Failed asserting that false is true.

/home/xenial/phpunittest/test.php:25

ERRORS!
Tests: 4, Assertions: 3, Errors: 1, Failures: 2.

PHPUnit 在使用@dataProvider 时不会跳过@depends 错误测试

来自their docs

注意

当测试依赖于使用数据提供者的测试时,依赖的测试将在它所依赖的测试对至少一个数据集成功时执行。

如果依赖测试中提供的数据的任何部分导致错误,我想一起跳过一些测试。有没有办法解决这个限制?


如果需要,您可以fork these files 进行快速测试,或者直接克隆:

git clone https://github.com/admonkey/phpunittest.git

【问题讨论】:

  • 有趣的想法。问题不在于他忽略了@depends - 他只是很满意其中一项数据测试有效......

标签: php unit-testing testing phpunit


【解决方案1】:

也许这是您期望的行为:

<?php

class DataProviderDependsTest extends PHPUnit_Framework_TestCase
{
    protected static $failed = false;

    public function getDataProvider() {
        return [
            ['real_file.txt'],
            ['non-existent_file.txt'],
        ];
    }

    /**
     * @dataProvider getDataProvider
     */
    public function testCanBeDependedOn($data) {
        try {
            $actual = file_get_contents($data);
            self::assertSame('expected', $actual);
        } catch(Exception $e) {
            self::$failed = true;
            throw $e;
        }
    }

    /**
     * @dataProvider getDataProvider
     * @depends testCanBeDependedOn
     */
    public function testCanDepend($data) {
        if (self::$failed) {
            self::markTestSkipped('testCanBeDependedOn failed');
        }
        self::assertTrue(true);
    }
}   

【讨论】:

    【解决方案2】:

    抱歉,此答案并不能真正解决您的问题,因为您确实需要在数据提供者中至少有一个通过记录才能运行基于 @depends 的测试。 @iRas 的答案看起来可以满足您的需求。

    我没有删除此答案,因为它可能仍会向其他人提供一些信息。

    @depends 没有实现您期望的功能。如果另一个失败,这并不意味着不运行测试。

    From the Manual for @depends:

    PHPUnit 支持声明测试方法之间的显式依赖关系。这种依赖关系没有定义测试方法的执行顺序,但它们允许生产者返回测试夹具的实例并将其传递给依赖的消费者。例 2.2 展示了如何使用 @depends 注解来表达测试方法之间的依赖关系。

    有关详细信息,请参阅名为“测试依赖项”的部分。

    这更多地用于在测试函数之间传递数据,而不是确保如果另一组测试失败,则一组测试不会运行。

    Sample Test in Documentation

    <?php
    use PHPUnit\Framework\TestCase;
    
    class StackTest extends TestCase
    {
        public function testEmpty()
        {
            $stack = [];
            $this->assertEmpty($stack);
    
            return $stack;
        }
    
        /**
         * @depends testEmpty
         */
        public function testPush(array $stack)
        {
            array_push($stack, 'foo');
            $this->assertEquals('foo', $stack[count($stack)-1]);
            $this->assertNotEmpty($stack);
    
            return $stack;
        }
    
        /**
         * @depends testPush
         */
        public function testPop(array $stack)
        {
            $this->assertEquals('foo', array_pop($stack));
            $this->assertEmpty($stack);
        }
    }
    ?>
    

    在测试中,来自 testEmpty() 的 $stack 被返回,并被传递给 testPush。这意味着 testPush 中的 $stack 已定义并且是一个空数组,而不是 undefined。

    理想情况下,您的测试不应该依赖于其中一个或另一个传递,并且是原子的以指示功能是否有效,以帮助发现代码中的问题。如果一个测试以一种意想不到的方式更改数据,那么基于测试通过的更多依赖关系可能会导致很多错误,那么所有后续检查该数据的测试都会失败,这并不是你应该如何构建测试的方式。测试良好的条件,测试失败,但在通过和失败的测试之间没有硬依赖。

    【讨论】:

    • 但是如果依赖测试失败,它会跳过测试......并且它可能会这样做,因为它说“这就是为什么 PHPUnit 在依赖测试失败时跳过测试的执行。”
    猜你喜欢
    • 2012-05-01
    • 1970-01-01
    • 2019-01-21
    • 2015-11-27
    • 2017-12-05
    • 2010-11-27
    • 2016-10-29
    • 2012-09-12
    相关资源
    最近更新 更多