diff --git a/src/Framework/TestCase.php b/src/Framework/TestCase.php index d931d3a5ad3..2ae873231ac 100644 --- a/src/Framework/TestCase.php +++ b/src/Framework/TestCase.php @@ -94,6 +94,11 @@ abstract class TestCase extends Assert implements SelfDescribing, Test */ private $inIsolation = false; + /** + * @var bool + */ + protected $forceCoversAnnotation = true; + /** * @var array */ @@ -1046,6 +1051,16 @@ public function isInIsolation(): bool return $this->inIsolation; } + public function setForceCoversAnnotation(bool $forceCoversAnnotation): void + { + $this->forceCoversAnnotation = $forceCoversAnnotation; + } + + public function getForceCoversAnnotation(): bool + { + return $this->forceCoversAnnotation; + } + public function getResult() { return $this->testResult; diff --git a/src/Framework/TestSuite.php b/src/Framework/TestSuite.php index f55c67fb539..86147f51e65 100644 --- a/src/Framework/TestSuite.php +++ b/src/Framework/TestSuite.php @@ -40,6 +40,11 @@ class TestSuite implements \IteratorAggregate, SelfDescribing, Test */ protected $runTestInSeparateProcess = false; + /** + * @var bool + */ + protected $forceCoversAnnotation = false; + /** * The name of the test suite. * @@ -542,6 +547,7 @@ public function run(TestResult $result = null): TestResult $test->setBackupGlobals($this->backupGlobals); $test->setBackupStaticAttributes($this->backupStaticAttributes); $test->setRunTestInSeparateProcess($this->runTestInSeparateProcess); + $test->setForceCoversAnnotation($this->forceCoversAnnotation); } $test->run($result); @@ -577,6 +583,11 @@ public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess): voi $this->runTestInSeparateProcess = $runTestInSeparateProcess; } + public function setForceCoversAnnotation(bool $forceCoversAnnotation): void + { + $this->forceCoversAnnotation = $forceCoversAnnotation; + } + public function setName(string $name): void { $this->name = $name; diff --git a/src/Util/Test.php b/src/Util/Test.php index f8339ba8f82..19576ad15c8 100644 --- a/src/Util/Test.php +++ b/src/Util/Test.php @@ -169,7 +169,11 @@ public static function requiresCodeCoverageDataCollection(TestCase $test): bool } // If there is no @coversNothing annotation then - // code coverage data may be collected + // fall back to the forceCoversAnnotation configuration. + if ($test->getForceCoversAnnotation()) { + return false; + } + return true; } diff --git a/tests/unit/Util/TestTest.php b/tests/unit/Util/TestTest.php index a04d147499a..8042a1453dd 100644 --- a/tests/unit/Util/TestTest.php +++ b/tests/unit/Util/TestTest.php @@ -1328,11 +1328,12 @@ public function testCoversAnnotationIncludesTraitsUsedByClass(): void /** * @dataProvider canSkipCoverageProvider */ - public function testCanSkipCoverage($testCase, $expectedCanSkip): void + public function testCanSkipCoverage($testCase, $expectedCanSkip, $forceCoversAnnotation): void { require_once TEST_FILES_PATH . $testCase . '.php'; $test = new $testCase('testSomething'); + $test->setForceCoversAnnotation($forceCoversAnnotation); $coverageRequired = Test::requiresCodeCoverageDataCollection($test); $canSkipCoverage = !$coverageRequired; @@ -1342,10 +1343,15 @@ public function testCanSkipCoverage($testCase, $expectedCanSkip): void public function canSkipCoverageProvider(): array { return [ - ['CoverageClassWithoutAnnotationsTest', false], - ['CoverageClassTest', false], - ['CoverageNothingTest', false], - ['CoverageCoversOverridesCoversNothingTest', false], + ['CoverageClassTest', false, false], + ['CoverageClassWithoutAnnotationsTest', false, false], + ['CoverageNothingTest', false, false], + ['CoverageCoversOverridesCoversNothingTest', false, false], + + ['CoverageClassTest', false, true], + ['CoverageClassWithoutAnnotationsTest', true, true], + ['CoverageNothingTest', false, true], + ['CoverageCoversOverridesCoversNothingTest', false, true], ]; }