Skip to content

Commit

Permalink
Closes #4260
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianbergmann committed Jun 13, 2020
1 parent 177f9ce commit 5f0dc4d
Show file tree
Hide file tree
Showing 14 changed files with 97 additions and 54 deletions.
2 changes: 1 addition & 1 deletion .psalm/baseline.xml
Expand Up @@ -219,7 +219,7 @@
<code>$loader</code>
</PossiblyNullPropertyAssignmentValue>
<PossiblyUndefinedVariable occurrences="1">
<code>$coverageFilterFromConfigurationFile</code>
<code>$codeCoverageConfiguration</code>
</PossiblyUndefinedVariable>
</file>
<file src="src/Util/Annotation/DocBlock.php">
Expand Down
4 changes: 4 additions & 0 deletions ChangeLog-9.3.md
Expand Up @@ -4,6 +4,10 @@ All notable changes of the PHPUnit 9.3 release series are documented in this fil

## [9.3.0] - 2020-08-07

### Added

* [#4260](https://github.com/sebastianbergmann/phpunit/issues/4260): `pathCoverage` attribute on the `phpunit/coverage` element of the XML configuration file for enabling path coverage for code coverage drivers that support it

### Changed

* [#4264](https://github.com/sebastianbergmann/phpunit/pull/4264): Refactor logical operator constraints
Expand Down
2 changes: 1 addition & 1 deletion phpunit.xml
Expand Up @@ -15,7 +15,7 @@
</testsuite>
</testsuites>

<coverage processUncoveredFiles="true">
<coverage pathCoverage="true" processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
Expand Down
1 change: 1 addition & 0 deletions phpunit.xsd
Expand Up @@ -29,6 +29,7 @@
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="pathCoverage" type="xs:boolean" default="false"/>
<xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/>
<xs:attribute name="processUncoveredFiles" type="xs:boolean" default="false"/>
<xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/>
Expand Down
7 changes: 7 additions & 0 deletions src/Framework/TestCase.php
Expand Up @@ -726,8 +726,14 @@ public function run(TestResult $result = null): TestResult
$phar = '\'\'';
}

$driverMethod = 'forLineCoverage';

if ($result->getCodeCoverage()) {
$codeCoverageFilter = $result->getCodeCoverage()->filter();

if ($result->getCodeCoverage()->collectsBranchAndPathCoverage()) {
$driverMethod = 'forLineAndPathCoverage';
}
} else {
$codeCoverageFilter = null;
}
Expand All @@ -753,6 +759,7 @@ public function run(TestResult $result = null): TestResult
'filename' => $class->getFileName(),
'className' => $class->getName(),
'collectCodeCoverageInformation' => $coverage,
'driverMethod' => $driverMethod,
'data' => $data,
'dataName' => $dataName,
'dependencyInput' => $dependencyInput,
Expand Down
6 changes: 4 additions & 2 deletions src/Runner/PhptTestCase.php
Expand Up @@ -162,7 +162,7 @@ public function run(TestResult $result = null): TestResult
}

if ($result->getCollectCodeCoverageInformation()) {
$this->renderForCoverage($code);
$this->renderForCoverage($code, $result->getCodeCoverage()->collectsBranchAndPathCoverage());
}

$timer = new Timer;
Expand Down Expand Up @@ -550,7 +550,7 @@ private function getCoverageFiles(): array
];
}

private function renderForCoverage(string &$job): void
private function renderForCoverage(string &$job, bool $pathCoverage): void
{
$files = $this->getCoverageFiles();

Expand Down Expand Up @@ -586,10 +586,12 @@ private function renderForCoverage(string &$job): void
'globals' => $globals,
'job' => $files['job'],
'coverageFile' => $files['coverage'],
'driverMethod' => $pathCoverage ? 'forLineAndPathCoverage' : 'forLineCoverage',
]
);

\file_put_contents($files['job'], $job);

$job = $template->render();
}

Expand Down
98 changes: 52 additions & 46 deletions src/TextUI/TestRunner.php
Expand Up @@ -465,12 +465,6 @@ public function run(TestSuite $suite, array $arguments = [], array $warnings = [
$codeCoverageReports = 0;
}

if ($codeCoverageReports > 0 && !$this->runtime->canCollectCodeCoverage()) {
$this->writeMessage('Error', 'No code coverage driver is available');

$codeCoverageReports = 0;
}

if ($codeCoverageReports > 0 || isset($arguments['xdebugFilterFile'])) {
$coverageFilterFromConfigurationFile = false;
$coverageFilterFromOption = false;
Expand Down Expand Up @@ -563,63 +557,75 @@ public function run(TestSuite $suite, array $arguments = [], array $warnings = [
}

if ($codeCoverageReports > 0) {
$codeCoverage = new CodeCoverage(
Driver::forLineCoverage($this->codeCoverageFilter),
$this->codeCoverageFilter
);
try {
if ($codeCoverageConfiguration->pathCoverage()) {
$driver = Driver::forLineAndPathCoverage($this->codeCoverageFilter);
} else {
$driver = Driver::forLineCoverage($this->codeCoverageFilter);
}

$codeCoverage->excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(Comparator::class);
$codeCoverage = new CodeCoverage(
$driver,
$this->codeCoverageFilter
);

if ($arguments['strictCoverage']) {
$codeCoverage->enableCheckForUnintentionallyCoveredCode();
}
$codeCoverage->excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(Comparator::class);

if (isset($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'])) {
if ($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage']) {
$codeCoverage->ignoreDeprecatedCode();
} else {
$codeCoverage->doNotIgnoreDeprecatedCode();
if ($arguments['strictCoverage']) {
$codeCoverage->enableCheckForUnintentionallyCoveredCode();
}
}

if (isset($arguments['disableCodeCoverageIgnore'])) {
if ($arguments['disableCodeCoverageIgnore']) {
$codeCoverage->disableAnnotationsForIgnoringCode();
} else {
$codeCoverage->enableAnnotationsForIgnoringCode();
if (isset($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'])) {
if ($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage']) {
$codeCoverage->ignoreDeprecatedCode();
} else {
$codeCoverage->doNotIgnoreDeprecatedCode();
}
}
}

if (isset($arguments['configuration'])) {
\assert($arguments['configuration'] instanceof Configuration);
if (isset($arguments['disableCodeCoverageIgnore'])) {
if ($arguments['disableCodeCoverageIgnore']) {
$codeCoverage->disableAnnotationsForIgnoringCode();
} else {
$codeCoverage->enableAnnotationsForIgnoringCode();
}
}

$codeCoverageConfiguration = $arguments['configuration']->codeCoverage();
if (isset($arguments['configuration'])) {
\assert($arguments['configuration'] instanceof Configuration);

if ($codeCoverageConfiguration->hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()) {
if ($codeCoverageConfiguration->includeUncoveredFiles()) {
$codeCoverage->includeUncoveredFiles();
} else {
$codeCoverage->excludeUncoveredFiles();
$codeCoverageConfiguration = $arguments['configuration']->codeCoverage();

if ($codeCoverageConfiguration->hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()) {
if ($codeCoverageConfiguration->includeUncoveredFiles()) {
$codeCoverage->includeUncoveredFiles();
} else {
$codeCoverage->excludeUncoveredFiles();
}

if ($codeCoverageConfiguration->processUncoveredFiles()) {
$codeCoverage->processUncoveredFiles();
} else {
$codeCoverage->doNotProcessUncoveredFiles();
}
}
}

if ($codeCoverageConfiguration->processUncoveredFiles()) {
$codeCoverage->processUncoveredFiles();
if ($this->codeCoverageFilter->isEmpty()) {
if (!$coverageFilterFromConfigurationFile && !$coverageFilterFromOption) {
$this->writeMessage('Warning', 'No filter is configured, code coverage will not be processed');
} else {
$codeCoverage->doNotProcessUncoveredFiles();
$this->writeMessage('Warning', 'Incorrect filter configuration, code coverage will not be processed');
}
}
}

if ($this->codeCoverageFilter->isEmpty()) {
if (!$coverageFilterFromConfigurationFile && !$coverageFilterFromOption) {
$this->writeMessage('Error', 'No filter is configured, no code coverage will be generated.');
} else {
$this->writeMessage('Error', 'Incorrect filter configuration, no code coverage will be generated.');
$codeCoverageReports = 0;

unset($codeCoverage);
}
} catch (CodeCoverageException $e) {
$this->writeMessage('Warning', $e->getMessage());

$codeCoverageReports = 0;

unset($codeCoverage);
}
}

Expand Down
13 changes: 12 additions & 1 deletion src/TextUI/XmlConfiguration/CodeCoverage/CodeCoverage.php
Expand Up @@ -45,6 +45,11 @@ final class CodeCoverage
*/
private $excludeFiles;

/**
* @var bool
*/
private $pathCoverage;

/**
* @var bool
*/
Expand Down Expand Up @@ -100,12 +105,13 @@ final class CodeCoverage
*/
private $xml;

public function __construct(DirectoryCollection $directories, FileCollection $files, DirectoryCollection $excludeDirectories, FileCollection $excludeFiles, bool $includeUncoveredFiles, bool $processUncoveredFiles, bool $cacheTokens, bool $ignoreDeprecatedCodeUnits, bool $disableCodeCoverageIgnore, ?Clover $clover, ?Crap4j $crap4j, ?Html $html, ?Php $php, ?Text $text, ?Xml $xml)
public function __construct(DirectoryCollection $directories, FileCollection $files, DirectoryCollection $excludeDirectories, FileCollection $excludeFiles, bool $pathCoverage, bool $includeUncoveredFiles, bool $processUncoveredFiles, bool $cacheTokens, bool $ignoreDeprecatedCodeUnits, bool $disableCodeCoverageIgnore, ?Clover $clover, ?Crap4j $crap4j, ?Html $html, ?Php $php, ?Text $text, ?Xml $xml)
{
$this->directories = $directories;
$this->files = $files;
$this->excludeDirectories = $excludeDirectories;
$this->excludeFiles = $excludeFiles;
$this->pathCoverage = $pathCoverage;
$this->includeUncoveredFiles = $includeUncoveredFiles;
$this->processUncoveredFiles = $processUncoveredFiles;
$this->cacheTokens = $cacheTokens;
Expand Down Expand Up @@ -144,6 +150,11 @@ public function excludeFiles(): FileCollection
return $this->excludeFiles;
}

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

public function includeUncoveredFiles(): bool
{
return $this->includeUncoveredFiles;
Expand Down
9 changes: 9 additions & 0 deletions src/TextUI/XmlConfiguration/Loader.php
Expand Up @@ -371,6 +371,7 @@ private function codeCoverage(string $filename, \DOMXPath $xpath, \DOMDocument $
return $this->legacyCodeCoverage($filename, $xpath, $document);
}

$pathCoverage = false;
$includeUncoveredFiles = true;
$processUncoveredFiles = false;
$cacheTokens = false;
Expand All @@ -380,6 +381,12 @@ private function codeCoverage(string $filename, \DOMXPath $xpath, \DOMDocument $
$element = $this->element($xpath, 'coverage');

if ($element) {
$pathCoverage = $this->getBooleanAttribute(
$element,
'pathCoverage',
false
);

$includeUncoveredFiles = $this->getBooleanAttribute(
$element,
'includeUncoveredFiles',
Expand Down Expand Up @@ -505,6 +512,7 @@ private function codeCoverage(string $filename, \DOMXPath $xpath, \DOMDocument $
$this->readFilterFiles($filename, $xpath, 'coverage/include/file'),
$this->readFilterDirectories($filename, $xpath, 'coverage/exclude/directory'),
$this->readFilterFiles($filename, $xpath, 'coverage/exclude/file'),
$pathCoverage,
$includeUncoveredFiles,
$processUncoveredFiles,
$cacheTokens,
Expand Down Expand Up @@ -637,6 +645,7 @@ private function legacyCodeCoverage(string $filename, \DOMXPath $xpath, \DOMDocu
$this->readFilterFiles($filename, $xpath, 'filter/whitelist/file'),
$this->readFilterDirectories($filename, $xpath, 'filter/whitelist/exclude/directory'),
$this->readFilterFiles($filename, $xpath, 'filter/whitelist/exclude/file'),
false,
$includeUncoveredFiles,
$processUncoveredFiles,
$cacheTokens,
Expand Down
2 changes: 1 addition & 1 deletion src/Util/PHP/Template/TestCaseClass.tpl
Expand Up @@ -40,7 +40,7 @@ function __phpunit_run_isolated_test()
$result->setCodeCoverage(
new CodeCoverage(
Driver::forLineCoverage($filter),
Driver::{driverMethod}($filter),
$filter
)
);
Expand Down
2 changes: 1 addition & 1 deletion src/Util/PHP/Template/TestCaseMethod.tpl
Expand Up @@ -41,7 +41,7 @@ function __phpunit_run_isolated_test()
$result->setCodeCoverage(
new CodeCoverage(
Driver::forLineCoverage($filter),
Driver::{driverMethod}($filter),
$filter
)
);
Expand Down
3 changes: 2 additions & 1 deletion tests/_files/configuration_codecoverage.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<phpunit>
<coverage includeUncoveredFiles="true"
<coverage pathCoverage="true"
includeUncoveredFiles="true"
processUncoveredFiles="true"
ignoreDeprecatedCodeUnits="true"
disableCodeCoverageIgnore="true"
Expand Down
1 change: 1 addition & 0 deletions tests/unit/TextUI/XmlConfigurationTest.php
Expand Up @@ -140,6 +140,7 @@ public function testCodeCoverageConfigurationIsReadCorrectly(): void
{
$codeCoverage = $this->configuration('configuration_codecoverage.xml')->codeCoverage();

$this->assertTrue($codeCoverage->pathCoverage());
$this->assertTrue($codeCoverage->includeUncoveredFiles());
$this->assertTrue($codeCoverage->processUncoveredFiles());
$this->assertTrue($codeCoverage->ignoreDeprecatedCodeUnits());
Expand Down
1 change: 1 addition & 0 deletions tests/unit/Util/XDebugFilterScriptGeneratorTest.php
Expand Up @@ -85,6 +85,7 @@ public function testReturnsExpectedScript(): void
),
DirectoryCollection::fromArray([]),
FileCollection::fromArray([]),
false,
true,
true,
false,
Expand Down

0 comments on commit 5f0dc4d

Please sign in to comment.