如何跳过 PHPUnit 中的错误测试?

How to skip tests on error in PHPUnit?

如何让 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 继续执行 all 依赖测试无论如何(即使相应的数据集有错误)。它不会跳过任何东西。 注意 添加了 ['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 不跳过 @depends tests on error when using @dataProvider

来自 their docs:

Note

When a test depends on a test that uses data providers, the depending test will be executed when the test it depends upon is successful for at least one data set.

如果依赖测试中提供的数据的任何部分导致错误,我想一起跳过一些测试。有什么方法可以解决此限制?


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

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

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

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

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

From the Manual for @depends:

PHPUnit supports the declaration of explicit dependencies between test methods. Such dependencies do not define the order in which the test methods are to be executed but they allow the returning of an instance of the test fixture by a producer and passing it to the dependent consumers. Example 2.2 shows how to use the @depends annotation to express dependencies between test methods.

See the section called “Test Dependencies” for more details.

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

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 已定义并且是一个空数组,而不是未定义。

理想情况下,您的测试不应该依赖于一个或另一个通过,并且是原子的以指示功能是否有效,以帮助发现代码中的问题。如果一个测试以非预期的方式更改数据,则基于测试通过的更多依赖项可能会导致大量错误,然后所有检查该数据的后续测试都将失败,这实际上不是您应该构建测试的方式。测试良好条件,测试失败,但在通过和失败测试之间没有硬依赖关系。

也许这是您期望的行为:

<?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);
    }
}