Skip to content

Commit

Permalink
Closes #4246
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianbergmann committed May 28, 2020
1 parent a7a3cf2 commit 61f7c75
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 19 deletions.
1 change: 1 addition & 0 deletions ChangeLog-9.2.md
Expand Up @@ -10,6 +10,7 @@ All notable changes of the PHPUnit 9.2 release series are documented in this fil

### Changed

* [#4246](https://github.com/sebastianbergmann/phpunit/issues/4246): Tests that are supposed to have a `@covers` annotation are now marked as risky even if code coverage is not collected
* The test runner no longer relies on `$_SERVER['REQUEST_TIME_FLOAT']` for printing the elapsed time

[9.2.0]: https://github.com/sebastianbergmann/phpunit/compare/9.1...master
1 change: 0 additions & 1 deletion src/Framework/TestCase.php
Expand Up @@ -632,7 +632,6 @@ public function hasFailed(): bool
* @throws UtilException
* @throws \SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException
* @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
* @throws \SebastianBergmann\CodeCoverage\MissingCoversAnnotationException
* @throws \SebastianBergmann\CodeCoverage\RuntimeException
* @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
Expand Down
41 changes: 29 additions & 12 deletions src/Framework/TestResult.php
Expand Up @@ -17,7 +17,6 @@
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException as OriginalCoveredCodeNotExecutedException;
use SebastianBergmann\CodeCoverage\Exception as OriginalCodeCoverageException;
use SebastianBergmann\CodeCoverage\MissingCoversAnnotationException as OriginalMissingCoversAnnotationException;
use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException;
use SebastianBergmann\Invoker\Invoker;
use SebastianBergmann\Invoker\TimeoutException;
Expand Down Expand Up @@ -158,6 +157,11 @@ final class TestResult implements \Countable
*/
private $enforceTimeLimit = false;

/**
* @var bool
*/
private $forceCoversAnnotation = false;

/**
* @var int
*/
Expand Down Expand Up @@ -596,7 +600,6 @@ public function getCollectCodeCoverageInformation(): bool
*
* @throws CodeCoverageException
* @throws OriginalCoveredCodeNotExecutedException
* @throws OriginalMissingCoversAnnotationException
* @throws UnintentionallyCoveredCodeException
* @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
* @throws \SebastianBergmann\CodeCoverage\RuntimeException
Expand Down Expand Up @@ -773,6 +776,20 @@ public function run(Test $test): void
$risky = true;
}

if ($this->forceCoversAnnotation) {
$annotations = $test->getAnnotations();

if (!isset($annotations['class']['covers']) && !isset($annotations['method']['covers'])) {
$this->addFailure(
$test,
new MissingCoversAnnotationException(
'This test does not have a @covers annotation but is expected to have one'
),
$time
);
}
}

if ($collectCodeCoverage) {
$append = !$risky && !$incomplete && !$skipped;
$linesToBeCovered = [];
Expand Down Expand Up @@ -824,16 +841,6 @@ public function run(Test $test): void
),
$time
);
} catch (OriginalMissingCoversAnnotationException $cce) {
if ($linesToBeCovered !== false) {
$this->addFailure(
$test,
new MissingCoversAnnotationException(
'This test does not have a @covers annotation but is expected to have one'
),
$time
);
}
} catch (OriginalCodeCoverageException $cce) {
$error = true;

Expand Down Expand Up @@ -1114,6 +1121,16 @@ public function isStrictAboutTodoAnnotatedTests(): bool
return $this->beStrictAboutTodoAnnotatedTests;
}

public function forceCoversAnnotation(): void
{
$this->forceCoversAnnotation = true;
}

public function forcesCoversAnnotation(): bool
{
return $this->forceCoversAnnotation;
}

/**
* Enables or disables the stopping for risky tests.
*/
Expand Down
1 change: 0 additions & 1 deletion src/Framework/TestSuite.php
Expand Up @@ -550,7 +550,6 @@ public function setGroupDetails(array $groups): void
* @throws \PHPUnit\Framework\CodeCoverageException
* @throws \SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException
* @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
* @throws \SebastianBergmann\CodeCoverage\MissingCoversAnnotationException
* @throws \SebastianBergmann\CodeCoverage\RuntimeException
* @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
Expand Down
1 change: 0 additions & 1 deletion src/Runner/PhptTestCase.php
Expand Up @@ -103,7 +103,6 @@ public function count(): int
* @throws Exception
* @throws \SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException
* @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
* @throws \SebastianBergmann\CodeCoverage\MissingCoversAnnotationException
* @throws \SebastianBergmann\CodeCoverage\RuntimeException
* @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
Expand Down
8 changes: 4 additions & 4 deletions src/TextUI/TestRunner.php
Expand Up @@ -541,10 +541,6 @@ public function run(TestSuite $suite, array $arguments = [], array $warnings = [
$arguments['strictCoverage']
);

$codeCoverage->setForceCoversAnnotation(
$arguments['forceCoversAnnotation']
);

if (isset($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'])) {
$codeCoverage->setIgnoreDeprecatedCode(
$arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage']
Expand Down Expand Up @@ -627,6 +623,10 @@ public function run(TestSuite $suite, array $arguments = [], array $warnings = [
$result->setTimeoutForMediumTests($arguments['timeoutForMediumTests']);
$result->setTimeoutForLargeTests($arguments['timeoutForLargeTests']);

if (isset($arguments['forceCoversAnnotation']) && $arguments['forceCoversAnnotation'] === true) {
$result->forceCoversAnnotation();
}

$this->processSuiteFilters($suite, $arguments);
$suite->setRunTestInSeparateProcess($arguments['processIsolation']);

Expand Down
24 changes: 24 additions & 0 deletions tests/end-to-end/force-covers-annotation.phpt
@@ -0,0 +1,24 @@
--TEST--
phpunit ../../_files/BankAccountTest.php
--FILE--
<?php declare(strict_types=1);
$_SERVER['argv'][1] = '--configuration';
$_SERVER['argv'][2] = __DIR__ . '/force-covers-annotation/phpunit.xml';
$_SERVER['argv'][3] = __DIR__ . '/force-covers-annotation/tests/Test.php';

require __DIR__ . '/../bootstrap.php';
PHPUnit\TextUI\Command::main();
--EXPECTF--
PHPUnit %s by Sebastian Bergmann and contributors.

R 1 / 1 (100%)

Time: %s, Memory: %s

There was 1 risky test:

1) Test::testOne
This test does not have a @covers annotation but is expected to have one

OK, but incomplete, skipped, or risky tests!
Tests: 1, Assertions: 1, Risky: 1.
16 changes: 16 additions & 0 deletions tests/end-to-end/force-covers-annotation/phpunit.xml
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.2/phpunit.xsd"
forceCoversAnnotation="true">
<testsuites>
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>

<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</phpunit>
18 changes: 18 additions & 0 deletions tests/end-to-end/force-covers-annotation/tests/Test.php
@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use PHPUnit\Framework\TestCase;

final class Test extends TestCase
{
public function testOne(): void
{
$this->assertTrue(true);
}
}

0 comments on commit 61f7c75

Please sign in to comment.