Skip to content

Deprecations in data provider affect all tests #6279

@nikophil

Description

@nikophil
Q A
PHPUnit version 12.2
PHP version any
Installation Method Composer

Since #6165, when a deprecation is triggered in a data provider, it affects all tests:

This test:

class TriggersDeprecationInDataProviderTest extends TestCase
{
    #[Test]
    public function method1(): void
    {
        self::assertTrue(true);
    }

    #[Test]
    #[DataProvider('dataProvider')]
    public function method2(bool $value): void
    {
        self::assertTrue($value);
    }

    public static function dataProvider(): iterable
    {
        @trigger_error('some deprecation', \E_USER_DEPRECATED);

        yield [true];
    }

    #[Test]
    public function method3(): void
    {
        self::assertTrue(true);
    }
}

would display this output:

DDD                                                                 3 / 3 (100%)

Time: 00:00.001, Memory: 16.00 MB

3 tests triggered 1 deprecation:

1) /home/nicolas/works/github.com/sebastianbergmann/phpunit/tests/end-to-end/deprecation-trigger/_files/deprecation-in-data-provider/tests/TriggersDeprecationInDataProviderTest.php:26
some deprecation

Triggered by:

* PHPUnit\TestFixture\DeprecationInDataProvider\TriggersDeprecationInDataProviderTest::method1
  /home/nicolas/works/github.com/sebastianbergmann/phpunit/tests/end-to-end/deprecation-trigger/_files/deprecation-in-data-provider/tests/TriggersDeprecationInDataProviderTest.php:12

* PHPUnit\TestFixture\DeprecationInDataProvider\TriggersDeprecationInDataProviderTest::method2#0
  /home/nicolas/works/github.com/sebastianbergmann/phpunit/tests/end-to-end/deprecation-trigger/_files/deprecation-in-data-provider/tests/TriggersDeprecationInDataProviderTest.php:19

* PHPUnit\TestFixture\DeprecationInDataProvider\TriggersDeprecationInDataProviderTest::method3
  /home/nicolas/works/github.com/sebastianbergmann/phpunit/tests/end-to-end/deprecation-trigger/_files/deprecation-in-data-provider/tests/TriggersDeprecationInDataProviderTest.php:32

OK, but there were issues!
Tests: 3, Assertions: 3, Deprecations: 1.

I think the problem is because ErrorHandler::$globalDeprecations is not emptied in ErrorHandler::triggerGlobalDeprecations().

A straightforward fix would be:

    private function triggerGlobalDeprecations(): void
    {
        foreach ($this->globalDeprecations ?? [] as $d) {
            $this->__invoke(...$d);
        }

+        $this->globalDeprecations = [];
    }

But this fix seems brittle:

  • all the "data provider deprecations" would be affected to the first test, although they are not related to this specific test
  • if this test has #[IgnoreDeprecation] attribute, all those "data provider deprecations" would suddenly disappear

One cool thing to do would be to manage to connect the "data provider deprecations" to their related test method.
So that the above test would output:

.D.                                                                 3 / 3 (100%)

Time: 00:00.001, Memory: 16.00 MB

1 test triggered 1 deprecation:

Maybe in ErrorHandler::deprecationHandler() we could guess from which test we're coming from (something similar to https://github.com/sebastianbergmann/phpunit/blob/main/src/Runner/ErrorHandler.php#L101 or by leveraging DataProviderMethodCalled/DataProviderMethodFinished events), and defer the trigger of the deprecation only when we reach the test(s) connected to the data provider?

WDYT?

/cc @soyuka

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugSomething is broken

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions