phpunit icon indicating copy to clipboard operation
phpunit copied to clipboard

Using DataProvider changes code coverage on Abstract class/method

Open atomiix opened this issue 3 weeks ago • 2 comments

Q A
PHPUnit version 12.5.2
PHP version 8.4.15
Installation Method Composer

Summary

Using a #[DataProvider] adds uncovered line on abstract method

Current behavior

Instantiate a child class in a DataProvider adds an uncovered line on the parent class.

How to reproduce

parent class:

<?php

declare(strict_types=1);

namespace App;

abstract class AbstractClass
{
    abstract public function abstractMethod(): string;
}

child class:

<?php

declare(strict_types=1);

namespace App;

class ChildClass extends AbstractClass
{
    public function abstractMethod(): string
    {
        return 'test';
    }
}

Test case without DataProvider:

<?php

namespace Test;

use PHPUnit\Framework\TestCase;
use App\ChildClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\CoversClass;

#[CoversClass(ChildClass::class)]
final class ChildClassTest extends TestCase
{
    public function testAbstractMethod(): void
    {
        $child = new ChildClass();
        $response = $child->abstractMethod();
        self::assertSame('test', $response);
    }
}

Code coverage 100%:

XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-text
PHPUnit 12.5.2 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.4.15 with Xdebug 3.5.0
Configuration: /Users/thomas/phpunit/phpunit.xml

.                                                                   1 / 1 (100%)

Time: 00:00.025, Memory: 18.00 MB

OK (1 test, 1 assertion)


Code Coverage Report:
  2025-12-10 13:51:45

 Summary:
  Classes: 100.00% (1/1)
  Methods: 100.00% (1/1)
  Lines:   100.00% (1/1)

App\ChildClass
  Methods: 100.00% ( 1/ 1)   Lines: 100.00% (  1/  1)

Test case with DataProvider:

<?php

namespace Test;

use PHPUnit\Framework\TestCase;
use App\ChildClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\CoversClass;

#[CoversClass(ChildClass::class)]
final class ChildClassTest extends TestCase
{
    #[DataProvider('dataProvider')]
    public function testAbstractMethod(): void
    {
        $child = new ChildClass();
        $response = $child->abstractMethod();
        self::assertSame('test', $response);
    }

    public static function dataProvider(): iterable
    {
        $child = new ChildClass();
        yield [];
    }
}

Code coverage 50%:

PHPUnit 12.5.2 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.4.15 with Xdebug 3.5.0
Configuration: /Users/thomas/phpunit/phpunit.xml

.                                                                   1 / 1 (100%)

Time: 00:00.023, Memory: 18.00 MB

OK (1 test, 1 assertion)


Code Coverage Report:
  2025-12-10 13:53:04

 Summary:
  Classes: 50.00% (1/2)
  Methods: 50.00% (1/2)
  Lines:   50.00% (1/2)

App\ChildClass
  Methods: 100.00% ( 1/ 1)   Lines: 100.00% (  1/  1)

Expected behavior

The DataProvider should not add uncovered lines on abstract methods.

atomiix avatar Dec 10 '25 13:12 atomiix

I am not sure what you are trying to report, sorry, did not have time to look into it more closely yet. However, please note that code run from a data provider method is not considered to be covered.

sebastianbergmann avatar Dec 10 '25 14:12 sebastianbergmann

For sure! Let me know if the issue is not clear enough though. I thought the code sample would be suffisant to understand the issue but I can try to explain it better if needed

atomiix avatar Dec 10 '25 14:12 atomiix