Skip to content

Commit fa8fc55

Browse files
Add support for code coverage reporting in OpenClover XML format
1 parent 3b77818 commit fa8fc55

17 files changed

+185
-3
lines changed

ChangeLog-12.2.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ All notable changes of the PHPUnit 12.2 release series are documented in this fi
66

77
### Added
88

9+
* `--coverage-openclover` CLI option and `<openclover>` XML configuration element to configure reporting of code coverage information in OpenClover XML format; unlike the existing Clover XML reporting that is controlled through the `--coverage-clover` CLI option and `<clover>` XML configuration element, which remains unchanged, the XML documents generated using these new options validate against the OpenClover project's XML schema definition, with one exception: we do not generate the `<testproject>` element. This feature is experimental and the generated XML might change in order to improve compliance with the OpenClover project's XML schema definition further. Such changes will be made in bugfix and/or minor releases even if they break backward compatibility.
910
* `--with-telemetry` CLI option that can be used together with `--debug` to print debugging information that includes telemetry information
1011
* The `TestCase::provideAdditionalInformation()` method can now be used to emit a `Test\AdditionalInformationProvided` event
1112
* The new `Test\AfterLastTestMethodFailed`, `Test\AfterTestMethodFailed`, `Test\BeforeFirstTestMethodFailed`, `Test\BeforeTestMethodFailed`, `Test\PostConditionFailed`, `Test\PreConditionFailed` events are now emitted instead of `Test\AfterLastTestMethodErrored`, `Test\AfterTestMethodErrored`, `Test\BeforeFirstTestMethodErrored`, `Test\BeforeTestMethodErrored`, `Test\PostConditionErrored`, `Test\PreConditionErrored` when the `Throwable` extends `AssertionFailedError` to distinguish between errors and failures triggered in hook methods

phpunit.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@
289289
<xs:element name="cobertura" type="logToFileType" minOccurs="0"/>
290290
<xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" />
291291
<xs:element name="html" type="coverageReportHtmlType" minOccurs="0" />
292+
<xs:element name="openclover" type="logToFileType" minOccurs="0"/>
292293
<xs:element name="php" type="logToFileType" minOccurs="0" />
293294
<xs:element name="text" type="coverageReportTextType" minOccurs="0" />
294295
<xs:element name="xml" type="logToDirectoryType" minOccurs="0" />

src/Runner/CodeCoverage.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use SebastianBergmann\CodeCoverage\Exception as CodeCoverageException;
2525
use SebastianBergmann\CodeCoverage\Filter;
2626
use SebastianBergmann\CodeCoverage\Report\Clover as CloverReport;
27+
use SebastianBergmann\CodeCoverage\Report\OpenClover as OpenCloverReport;
2728
use SebastianBergmann\CodeCoverage\Report\Cobertura as CoberturaReport;
2829
use SebastianBergmann\CodeCoverage\Report\Crap4j as Crap4jReport;
2930
use SebastianBergmann\CodeCoverage\Report\Html\Colors;
@@ -297,6 +298,21 @@ public function generateReports(Printer $printer, Configuration $configuration):
297298
}
298299
}
299300

301+
if ($configuration->hasCoverageOpenClover()) {
302+
$this->codeCoverageGenerationStart($printer, 'OpenClover XML');
303+
304+
try {
305+
$writer = new OpenCloverReport;
306+
$writer->process($this->codeCoverage(), $configuration->coverageOpenClover(), 'OpenClover Coverage');
307+
308+
$this->codeCoverageGenerationSucceeded($printer);
309+
310+
unset($writer);
311+
} catch (CodeCoverageException $e) {
312+
$this->codeCoverageGenerationFailed($printer, $e);
313+
}
314+
}
315+
300316
if ($configuration->hasCoverageCobertura()) {
301317
$this->codeCoverageGenerationStart($printer, 'Cobertura XML');
302318

src/TextUI/Configuration/Cli/Builder.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ final class Builder
5050
'coverage-cobertura=',
5151
'coverage-crap4j=',
5252
'coverage-html=',
53+
'coverage-openclover=',
5354
'coverage-php=',
5455
'coverage-text==',
5556
'only-summary-for-coverage-text',
@@ -191,6 +192,7 @@ public function fromParameters(array $parameters): Configuration
191192
$coverageCobertura = null;
192193
$coverageCrap4J = null;
193194
$coverageHtml = null;
195+
$coverageOpenClover = null;
194196
$coveragePhp = null;
195197
$coverageText = null;
196198
$coverageTextShowUncoveredFiles = null;
@@ -361,6 +363,11 @@ public function fromParameters(array $parameters): Configuration
361363

362364
break;
363365

366+
case '--coverage-openclover':
367+
$coverageOpenClover = $option[1];
368+
369+
break;
370+
364371
case '--coverage-text':
365372
if ($option[1] === null) {
366373
$option[1] = 'php://stdout';
@@ -1022,6 +1029,7 @@ public function fromParameters(array $parameters): Configuration
10221029
$coverageCobertura,
10231030
$coverageCrap4J,
10241031
$coverageHtml,
1032+
$coverageOpenClover,
10251033
$coveragePhp,
10261034
$coverageText,
10271035
$coverageTextShowUncoveredFiles,

src/TextUI/Configuration/Cli/Configuration.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
private ?string $coverageCobertura;
4343
private ?string $coverageCrap4J;
4444
private ?string $coverageHtml;
45+
private ?string $coverageOpenClover;
4546
private ?string $coveragePhp;
4647
private ?string $coverageText;
4748
private ?bool $coverageTextShowUncoveredFiles;
@@ -179,7 +180,7 @@
179180
* @param ?non-empty-list<non-empty-string> $coverageFilter
180181
* @param ?non-empty-list<non-empty-string> $extensions
181182
*/
182-
public function __construct(array $arguments, ?string $atLeastVersion, ?bool $backupGlobals, ?bool $backupStaticProperties, ?bool $beStrictAboutChangesToGlobalState, ?string $bootstrap, ?string $cacheDirectory, ?bool $cacheResult, bool $checkVersion, ?string $colors, null|int|string $columns, ?string $configurationFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4J, ?string $coverageHtml, ?string $coveragePhp, ?string $coverageText, ?bool $coverageTextShowUncoveredFiles, ?bool $coverageTextShowOnlySummary, ?string $coverageXml, ?bool $pathCoverage, bool $warmCoverageCache, ?int $defaultTimeLimit, ?bool $disableCodeCoverageIgnore, ?bool $disallowTestOutput, ?bool $enforceTimeLimit, ?array $excludeGroups, ?int $executionOrder, ?int $executionOrderDefects, ?bool $failOnAllIssues, ?bool $failOnDeprecation, ?bool $failOnPhpunitDeprecation, ?bool $failOnPhpunitNotice, ?bool $failOnEmptyTestSuite, ?bool $failOnIncomplete, ?bool $failOnNotice, ?bool $failOnRisky, ?bool $failOnSkipped, ?bool $failOnWarning, ?bool $stopOnDefect, ?bool $stopOnDeprecation, ?string $specificDeprecationToStopOn, ?bool $stopOnError, ?bool $stopOnFailure, ?bool $stopOnIncomplete, ?bool $stopOnNotice, ?bool $stopOnRisky, ?bool $stopOnSkipped, ?bool $stopOnWarning, ?string $filter, ?string $excludeFilter, ?string $generateBaseline, ?string $useBaseline, bool $ignoreBaseline, bool $generateConfiguration, bool $migrateConfiguration, ?array $groups, ?array $testsCovering, ?array $testsUsing, ?array $testsRequiringPhpExtension, bool $help, ?string $includePath, ?array $iniSettings, ?string $junitLogfile, bool $listGroups, bool $listSuites, bool $listTestFiles, bool $listTests, ?string $listTestsXml, ?bool $noCoverage, ?bool $noExtensions, ?bool $noOutput, ?bool $noProgress, ?bool $noResults, ?bool $noLogging, ?bool $processIsolation, ?int $randomOrderSeed, ?bool $reportUselessTests, ?bool $resolveDependencies, ?bool $reverseList, ?bool $stderr, ?bool $strictCoverage, ?string $teamcityLogfile, ?string $testdoxHtmlFile, ?string $testdoxTextFile, ?array $testSuffixes, ?string $testSuite, ?string $excludeTestSuite, bool $useDefaultConfiguration, ?bool $displayDetailsOnAllIssues, ?bool $displayDetailsOnIncompleteTests, ?bool $displayDetailsOnSkippedTests, ?bool $displayDetailsOnTestsThatTriggerDeprecations, ?bool $displayDetailsOnPhpunitDeprecations, ?bool $displayDetailsOnPhpunitNotices, ?bool $displayDetailsOnTestsThatTriggerErrors, ?bool $displayDetailsOnTestsThatTriggerNotices, ?bool $displayDetailsOnTestsThatTriggerWarnings, bool $version, ?array $coverageFilter, ?string $logEventsText, ?string $logEventsVerboseText, ?bool $printerTeamCity, ?bool $testdoxPrinter, ?bool $testdoxPrinterSummary, bool $debug, bool $withTelemetry, ?array $extensions)
183+
public function __construct(array $arguments, ?string $atLeastVersion, ?bool $backupGlobals, ?bool $backupStaticProperties, ?bool $beStrictAboutChangesToGlobalState, ?string $bootstrap, ?string $cacheDirectory, ?bool $cacheResult, bool $checkVersion, ?string $colors, null|int|string $columns, ?string $configurationFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4J, ?string $coverageHtml, ?string $coverageOpenClover, ?string $coveragePhp, ?string $coverageText, ?bool $coverageTextShowUncoveredFiles, ?bool $coverageTextShowOnlySummary, ?string $coverageXml, ?bool $pathCoverage, bool $warmCoverageCache, ?int $defaultTimeLimit, ?bool $disableCodeCoverageIgnore, ?bool $disallowTestOutput, ?bool $enforceTimeLimit, ?array $excludeGroups, ?int $executionOrder, ?int $executionOrderDefects, ?bool $failOnAllIssues, ?bool $failOnDeprecation, ?bool $failOnPhpunitDeprecation, ?bool $failOnPhpunitNotice, ?bool $failOnEmptyTestSuite, ?bool $failOnIncomplete, ?bool $failOnNotice, ?bool $failOnRisky, ?bool $failOnSkipped, ?bool $failOnWarning, ?bool $stopOnDefect, ?bool $stopOnDeprecation, ?string $specificDeprecationToStopOn, ?bool $stopOnError, ?bool $stopOnFailure, ?bool $stopOnIncomplete, ?bool $stopOnNotice, ?bool $stopOnRisky, ?bool $stopOnSkipped, ?bool $stopOnWarning, ?string $filter, ?string $excludeFilter, ?string $generateBaseline, ?string $useBaseline, bool $ignoreBaseline, bool $generateConfiguration, bool $migrateConfiguration, ?array $groups, ?array $testsCovering, ?array $testsUsing, ?array $testsRequiringPhpExtension, bool $help, ?string $includePath, ?array $iniSettings, ?string $junitLogfile, bool $listGroups, bool $listSuites, bool $listTestFiles, bool $listTests, ?string $listTestsXml, ?bool $noCoverage, ?bool $noExtensions, ?bool $noOutput, ?bool $noProgress, ?bool $noResults, ?bool $noLogging, ?bool $processIsolation, ?int $randomOrderSeed, ?bool $reportUselessTests, ?bool $resolveDependencies, ?bool $reverseList, ?bool $stderr, ?bool $strictCoverage, ?string $teamcityLogfile, ?string $testdoxHtmlFile, ?string $testdoxTextFile, ?array $testSuffixes, ?string $testSuite, ?string $excludeTestSuite, bool $useDefaultConfiguration, ?bool $displayDetailsOnAllIssues, ?bool $displayDetailsOnIncompleteTests, ?bool $displayDetailsOnSkippedTests, ?bool $displayDetailsOnTestsThatTriggerDeprecations, ?bool $displayDetailsOnPhpunitDeprecations, ?bool $displayDetailsOnPhpunitNotices, ?bool $displayDetailsOnTestsThatTriggerErrors, ?bool $displayDetailsOnTestsThatTriggerNotices, ?bool $displayDetailsOnTestsThatTriggerWarnings, bool $version, ?array $coverageFilter, ?string $logEventsText, ?string $logEventsVerboseText, ?bool $printerTeamCity, ?bool $testdoxPrinter, ?bool $testdoxPrinterSummary, bool $debug, bool $withTelemetry, ?array $extensions)
183184
{
184185
$this->arguments = $arguments;
185186
$this->atLeastVersion = $atLeastVersion;
@@ -198,6 +199,7 @@ public function __construct(array $arguments, ?string $atLeastVersion, ?bool $ba
198199
$this->coverageCobertura = $coverageCobertura;
199200
$this->coverageCrap4J = $coverageCrap4J;
200201
$this->coverageHtml = $coverageHtml;
202+
$this->coverageOpenClover = $coverageOpenClover;
201203
$this->coveragePhp = $coveragePhp;
202204
$this->coverageText = $coverageText;
203205
$this->coverageTextShowUncoveredFiles = $coverageTextShowUncoveredFiles;
@@ -607,6 +609,26 @@ public function coverageHtml(): string
607609
return $this->coverageHtml;
608610
}
609611

612+
/**
613+
* @phpstan-assert-if-true !null $this->coverageOpenClover
614+
*/
615+
public function hasCoverageOpenClover(): bool
616+
{
617+
return $this->coverageOpenClover !== null;
618+
}
619+
620+
/**
621+
* @throws Exception
622+
*/
623+
public function coverageOpenClover(): string
624+
{
625+
if (!$this->hasCoverageOpenClover()) {
626+
throw new Exception;
627+
}
628+
629+
return $this->coverageOpenClover;
630+
}
631+
610632
/**
611633
* @phpstan-assert-if-true !null $this->coveragePhp
612634
*/

0 commit comments

Comments
 (0)