From bbb0245bd39aedb09b2de3497390d783b3d15a22 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Wed, 21 May 2025 14:03:24 +0200 Subject: [PATCH 01/21] Download https://raw.githubusercontent.com/openclover/clover/refs/tags/openclover-4.5.2/clover-core/src/main/resources/clover.xsd --- tests/_files/clover.xsd | 236 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 tests/_files/clover.xsd diff --git a/tests/_files/clover.xsd b/tests/_files/clover.xsd new file mode 100644 index 000000000..3597fa68e --- /dev/null +++ b/tests/_files/clover.xsd @@ -0,0 +1,236 @@ + + + + + + + Top-most element describing the coverage report. Contains a + project and a test project. + + + + + + + + + + + + + + Project metrics relating to non-test source. + @name - project name (optional) + @timestamp - seconds since UTC + + + + + + + + + + + + + + + Project metrics relating to test source. + @name - project name (optional) + @timestamp - seconds since UTC + + + + + + + + + + + + + + + Package metrics. + @name - the.package.name + + + + + + + + + + + + + + File metrics. + @name - the file name e.g. Foo.java or Bar.groovy + @path - the filesystem-specific original path to the file e.g. c:\path\to\Bar.groovy + + + + + + + + + + + + + + + + Class metrics. + @name - the unqualified class name + + + + + + + + + + + + + + + + + + + + + Line-specific information. + @line - the line number + @type - the type of syntactic construct - one of method|stmt|cond + @complexity - only applicable if @type == 'method'; the cyclomatic complexity of the construct + @count - only applicable if @type == 'stmt' or 'method'; the number of times the construct was executed + @truecount - only applicable if @type == 'cond'; the number of times the true branch was executed + @falsecount - only applicable if @type == 'cond'; the number of times the false branch was executed + @signature - only applicable if @type == 'method'; the signature of the method + @testduration - only applicable if @type == 'method' and the method was identified as a test method; the duration of the test + @testsuccess - only applicable if @type == 'method' and the method was identified as a test method; true if the test passed, false otherwise + @visibility - only applicable if @type == 'method' + + + + + + + + + + + + + + + + + + + + Metrics information for projects/packages/files/classes. + @complexity - the cyclomatic complexity + @conditionals - the number of contained conditionals (2 * number of branches) + @coveredconditionals - the number of contained conditionals (2 * number of branches) with coverage + @elements - the number of contained statements, conditionals and methods + @coveredelements - the number of contained statements, conditionals and methods with coverage + @statements - the number of contained statements + @coveredstatements - the number of contained statements with coverage + @methods - the number of contained methods + @coveredmethods - the number of contained methods with coverage + @testduration - the total duration of all contained test methods + @testfailures - the total number of test method failures + @testpasses - the total number of test method passes + @testruns - the total number of test methods run + + + + + + + + + + + + + + + + + + + + + Metrics information for projects/packages/files. + @classes - the total number of contained classes + @loc - the total number of lines of code + @ncloc - the total number of non-comment lines of code + + + + + + + + + + + + + + Metrics information for projects/packages. + @files - the total number of contained files + + + + + + + + + + + + Metrics information for projects. + @files - the total number of packages + + + + + + + + + + + + + + + + + + + + + + + + + + From ddbe9785925534f7e312c10b6787add8c84201b9 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Wed, 21 May 2025 14:03:51 +0200 Subject: [PATCH 02/21] Validate generated Clover XML against Clover XSD --- tests/tests/Report/CloverTest.php | 49 ++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/tests/tests/Report/CloverTest.php b/tests/tests/Report/CloverTest.php index 434415772..60f093314 100644 --- a/tests/tests/Report/CloverTest.php +++ b/tests/tests/Report/CloverTest.php @@ -9,6 +9,13 @@ */ namespace SebastianBergmann\CodeCoverage\Report; +use const PHP_EOL; +use function libxml_clear_errors; +use function libxml_get_errors; +use function libxml_use_internal_errors; +use function sprintf; +use function trim; +use DOMDocument; use PHPUnit\Framework\Attributes\CoversClass; use SebastianBergmann\CodeCoverage\TestCase; @@ -19,7 +26,7 @@ public function testLineCoverageForBankAccountTest(): void { $clover = new Clover; - $this->assertStringMatchesFormatFile( + $this->validateAndAssert( TEST_FILES_PATH . 'BankAccount-clover-line.xml', $clover->process($this->getLineCoverageForBankAccount(), null, 'BankAccount'), ); @@ -29,7 +36,7 @@ public function testPathCoverageForBankAccountTest(): void { $clover = new Clover; - $this->assertStringMatchesFormatFile( + $this->validateAndAssert( TEST_FILES_PATH . 'BankAccount-clover-path.xml', $clover->process($this->getPathCoverageForBankAccount(), null, 'BankAccount'), ); @@ -39,7 +46,7 @@ public function testCloverForFileWithIgnoredLines(): void { $clover = new Clover; - $this->assertStringMatchesFormatFile( + $this->validateAndAssert( TEST_FILES_PATH . 'ignored-lines-clover.xml', $clover->process($this->getCoverageForFileWithIgnoredLines()), ); @@ -49,9 +56,43 @@ public function testCloverForClassWithAnonymousFunction(): void { $clover = new Clover; - $this->assertStringMatchesFormatFile( + $this->validateAndAssert( TEST_FILES_PATH . 'class-with-anonymous-function-clover.xml', $clover->process($this->getCoverageForClassWithAnonymousFunction()), ); } + + /** + * @param non-empty-string $expectationFile + * @param non-empty-string $cloverXml + */ + private function validateAndAssert(string $expectationFile, string $cloverXml): void + { + libxml_use_internal_errors(true); + + $document = new DOMDocument; + $document->loadXML($cloverXml); + + if (!$document->schemaValidate(__DIR__ . '/../../_files/clover.xsd')) { + $buffer = 'Generated XML document does not validate against Clover schema:' . PHP_EOL . PHP_EOL; + + foreach (libxml_get_errors() as $error) { + $buffer .= sprintf( + '- Line %d: %s' . PHP_EOL, + $error->line, + trim($error->message), + ); + } + + $buffer .= PHP_EOL; + } + + libxml_clear_errors(); + + if (isset($buffer)) { + $this->fail($buffer); + } + + $this->assertStringMatchesFormatFile($expectationFile, $cloverXml); + } } From 103f221e0851ef0e459299798257780caededdf6 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Wed, 21 May 2025 14:54:01 +0200 Subject: [PATCH 03/21] Set clover attribute of element to version identifier for phpunit/php-code-coverage --- src/Report/Clover.php | 2 ++ tests/_files/BankAccount-clover-line.xml | 2 +- tests/_files/BankAccount-clover-path.xml | 2 +- tests/_files/class-with-anonymous-function-clover.xml | 2 +- tests/_files/ignored-lines-clover.xml | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index a5f1c09e6..0f21c192b 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -22,6 +22,7 @@ use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Node\File; use SebastianBergmann\CodeCoverage\Util\Filesystem; +use SebastianBergmann\CodeCoverage\Version; use SebastianBergmann\CodeCoverage\WriteOperationFailedException; final class Clover @@ -37,6 +38,7 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlDocument->formatOutput = true; $xmlCoverage = $xmlDocument->createElement('coverage'); + $xmlCoverage->setAttribute('clover', Version::id()); $xmlCoverage->setAttribute('generated', $time); $xmlDocument->appendChild($xmlCoverage); diff --git a/tests/_files/BankAccount-clover-line.xml b/tests/_files/BankAccount-clover-line.xml index 9a6fca706..2345871ce 100644 --- a/tests/_files/BankAccount-clover-line.xml +++ b/tests/_files/BankAccount-clover-line.xml @@ -1,5 +1,5 @@ - + diff --git a/tests/_files/BankAccount-clover-path.xml b/tests/_files/BankAccount-clover-path.xml index b49f4c915..617d84b37 100644 --- a/tests/_files/BankAccount-clover-path.xml +++ b/tests/_files/BankAccount-clover-path.xml @@ -1,5 +1,5 @@ - + diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/class-with-anonymous-function-clover.xml index 34a84690a..27e815100 100644 --- a/tests/_files/class-with-anonymous-function-clover.xml +++ b/tests/_files/class-with-anonymous-function-clover.xml @@ -1,5 +1,5 @@ - + diff --git a/tests/_files/ignored-lines-clover.xml b/tests/_files/ignored-lines-clover.xml index 39a32558a..f3bc1edf6 100644 --- a/tests/_files/ignored-lines-clover.xml +++ b/tests/_files/ignored-lines-clover.xml @@ -1,5 +1,5 @@ - + From 16f80f99d62eed2b2cdbf176c1c02b09dc06d9ac Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Wed, 21 May 2025 14:55:36 +0200 Subject: [PATCH 04/21] Perform validation after comparison with expectation --- tests/tests/Report/CloverTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/tests/Report/CloverTest.php b/tests/tests/Report/CloverTest.php index 60f093314..e406e27c1 100644 --- a/tests/tests/Report/CloverTest.php +++ b/tests/tests/Report/CloverTest.php @@ -68,6 +68,8 @@ public function testCloverForClassWithAnonymousFunction(): void */ private function validateAndAssert(string $expectationFile, string $cloverXml): void { + $this->assertStringMatchesFormatFile($expectationFile, $cloverXml); + libxml_use_internal_errors(true); $document = new DOMDocument; @@ -92,7 +94,5 @@ private function validateAndAssert(string $expectationFile, string $cloverXml): if (isset($buffer)) { $this->fail($buffer); } - - $this->assertStringMatchesFormatFile($expectationFile, $cloverXml); } } From feaa804fb3b9832c5b15054e572c39249eb5636f Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Wed, 21 May 2025 14:58:19 +0200 Subject: [PATCH 05/21] Remove superfluous type annotation --- src/Report/Clover.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index 0f21c192b..2afe9021f 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -59,8 +59,6 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string continue; } - /* @var File $item */ - $xmlFile = $xmlDocument->createElement('file'); $xmlFile->setAttribute('name', $item->pathAsString()); From f40356aed17f526c51b3922b54157c23907a4ec2 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 08:08:43 +0200 Subject: [PATCH 06/21] Make element the first child of and --- src/Report/Clover.php | 6 +++--- tests/_files/BankAccount-clover-line.xml | 4 ++-- tests/_files/BankAccount-clover-path.xml | 4 ++-- tests/_files/class-with-anonymous-function-clover.xml | 4 ++-- tests/_files/ignored-lines-clover.xml | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index 2afe9021f..e7e93ead8 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -127,7 +127,7 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements); $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class['executableBranches'])); $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class['executedBranches'])); - $xmlClass->appendChild($xmlMetrics); + $xmlClass->insertBefore($xmlMetrics, $xmlClass->firstChild); } foreach ($coverageData as $line => $data) { @@ -181,7 +181,7 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlMetrics->setAttribute('coveredstatements', (string) $item->numberOfExecutedLines()); $xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); - $xmlFile->appendChild($xmlMetrics); + $xmlFile->insertBefore($xmlMetrics, $xmlFile->firstChild); if ($namespace === 'global') { $xmlProject->appendChild($xmlFile); @@ -214,7 +214,7 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlMetrics->setAttribute('coveredstatements', (string) $report->numberOfExecutedLines()); $xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches())); $xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches())); - $xmlProject->appendChild($xmlMetrics); + $xmlProject->insertBefore($xmlMetrics, $xmlProject->firstChild); $buffer = $xmlDocument->saveXML(); diff --git a/tests/_files/BankAccount-clover-line.xml b/tests/_files/BankAccount-clover-line.xml index 2345871ce..312ccfb2e 100644 --- a/tests/_files/BankAccount-clover-line.xml +++ b/tests/_files/BankAccount-clover-line.xml @@ -1,7 +1,9 @@ + + @@ -17,8 +19,6 @@ - - diff --git a/tests/_files/BankAccount-clover-path.xml b/tests/_files/BankAccount-clover-path.xml index 617d84b37..3130b6620 100644 --- a/tests/_files/BankAccount-clover-path.xml +++ b/tests/_files/BankAccount-clover-path.xml @@ -1,7 +1,9 @@ + + @@ -17,8 +19,6 @@ - - diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/class-with-anonymous-function-clover.xml index 27e815100..0ec08ea8b 100644 --- a/tests/_files/class-with-anonymous-function-clover.xml +++ b/tests/_files/class-with-anonymous-function-clover.xml @@ -1,7 +1,9 @@ + + @@ -14,8 +16,6 @@ - - diff --git a/tests/_files/ignored-lines-clover.xml b/tests/_files/ignored-lines-clover.xml index f3bc1edf6..ac684de49 100644 --- a/tests/_files/ignored-lines-clover.xml +++ b/tests/_files/ignored-lines-clover.xml @@ -1,7 +1,9 @@ + + @@ -9,8 +11,6 @@ - - From e9b326085e5db36ba016f434adc66ba5491d1566 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 08:14:35 +0200 Subject: [PATCH 07/21] Set both name and path attributes on the element --- src/Report/Clover.php | 4 +++- tests/_files/BankAccount-clover-line.xml | 2 +- tests/_files/BankAccount-clover-path.xml | 2 +- tests/_files/class-with-anonymous-function-clover.xml | 2 +- tests/_files/ignored-lines-clover.xml | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index e7e93ead8..aa2c1c33b 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -9,6 +9,7 @@ */ namespace SebastianBergmann\CodeCoverage\Report; +use function basename; use function count; use function dirname; use function file_put_contents; @@ -60,7 +61,8 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string } $xmlFile = $xmlDocument->createElement('file'); - $xmlFile->setAttribute('name', $item->pathAsString()); + $xmlFile->setAttribute('name', basename($item->pathAsString())); + $xmlFile->setAttribute('path', $item->pathAsString()); $classes = $item->classesAndTraits(); $coverageData = $item->lineCoverageData(); diff --git a/tests/_files/BankAccount-clover-line.xml b/tests/_files/BankAccount-clover-line.xml index 312ccfb2e..29c55a39b 100644 --- a/tests/_files/BankAccount-clover-line.xml +++ b/tests/_files/BankAccount-clover-line.xml @@ -2,7 +2,7 @@ - + diff --git a/tests/_files/BankAccount-clover-path.xml b/tests/_files/BankAccount-clover-path.xml index 3130b6620..c965427eb 100644 --- a/tests/_files/BankAccount-clover-path.xml +++ b/tests/_files/BankAccount-clover-path.xml @@ -2,7 +2,7 @@ - + diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/class-with-anonymous-function-clover.xml index 0ec08ea8b..4ff8a7ac8 100644 --- a/tests/_files/class-with-anonymous-function-clover.xml +++ b/tests/_files/class-with-anonymous-function-clover.xml @@ -2,7 +2,7 @@ - + diff --git a/tests/_files/ignored-lines-clover.xml b/tests/_files/ignored-lines-clover.xml index ac684de49..a064f7407 100644 --- a/tests/_files/ignored-lines-clover.xml +++ b/tests/_files/ignored-lines-clover.xml @@ -2,7 +2,7 @@ - + From 4284f0fb7a54312cd6b1f567127948b2c7e939b6 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 08:17:58 +0200 Subject: [PATCH 08/21] Rename method to reflect that we assert before we validate --- tests/tests/Report/CloverTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/tests/Report/CloverTest.php b/tests/tests/Report/CloverTest.php index e406e27c1..4df3f74bf 100644 --- a/tests/tests/Report/CloverTest.php +++ b/tests/tests/Report/CloverTest.php @@ -26,7 +26,7 @@ public function testLineCoverageForBankAccountTest(): void { $clover = new Clover; - $this->validateAndAssert( + $this->assertAndValidate( TEST_FILES_PATH . 'BankAccount-clover-line.xml', $clover->process($this->getLineCoverageForBankAccount(), null, 'BankAccount'), ); @@ -36,7 +36,7 @@ public function testPathCoverageForBankAccountTest(): void { $clover = new Clover; - $this->validateAndAssert( + $this->assertAndValidate( TEST_FILES_PATH . 'BankAccount-clover-path.xml', $clover->process($this->getPathCoverageForBankAccount(), null, 'BankAccount'), ); @@ -46,7 +46,7 @@ public function testCloverForFileWithIgnoredLines(): void { $clover = new Clover; - $this->validateAndAssert( + $this->assertAndValidate( TEST_FILES_PATH . 'ignored-lines-clover.xml', $clover->process($this->getCoverageForFileWithIgnoredLines()), ); @@ -56,7 +56,7 @@ public function testCloverForClassWithAnonymousFunction(): void { $clover = new Clover; - $this->validateAndAssert( + $this->assertAndValidate( TEST_FILES_PATH . 'class-with-anonymous-function-clover.xml', $clover->process($this->getCoverageForClassWithAnonymousFunction()), ); @@ -66,7 +66,7 @@ public function testCloverForClassWithAnonymousFunction(): void * @param non-empty-string $expectationFile * @param non-empty-string $cloverXml */ - private function validateAndAssert(string $expectationFile, string $cloverXml): void + private function assertAndValidate(string $expectationFile, string $cloverXml): void { $this->assertStringMatchesFormatFile($expectationFile, $cloverXml); From 7a6b2cb6cdb9a58dfe90f1bf17cbdf39ddebff02 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 08:24:51 +0200 Subject: [PATCH 09/21] Generate element for global namespace --- src/Report/Clover.php | 20 ++++------ tests/_files/BankAccount-clover-line.xml | 38 ++++++++++--------- tests/_files/BankAccount-clover-path.xml | 38 ++++++++++--------- .../class-with-anonymous-function-clover.xml | 32 ++++++++-------- tests/_files/ignored-lines-clover.xml | 22 ++++++----- 5 files changed, 77 insertions(+), 73 deletions(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index aa2c1c33b..7270a82ae 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -185,20 +185,16 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); $xmlFile->insertBefore($xmlMetrics, $xmlFile->firstChild); - if ($namespace === 'global') { - $xmlProject->appendChild($xmlFile); - } else { - if (!isset($packages[$namespace])) { - $packages[$namespace] = $xmlDocument->createElement( - 'package', - ); - - $packages[$namespace]->setAttribute('name', $namespace); - $xmlProject->appendChild($packages[$namespace]); - } + if (!isset($packages[$namespace])) { + $packages[$namespace] = $xmlDocument->createElement( + 'package', + ); - $packages[$namespace]->appendChild($xmlFile); + $packages[$namespace]->setAttribute('name', $namespace); + $xmlProject->appendChild($packages[$namespace]); } + + $packages[$namespace]->appendChild($xmlFile); } $linesOfCode = $report->linesOfCode(); diff --git a/tests/_files/BankAccount-clover-line.xml b/tests/_files/BankAccount-clover-line.xml index 29c55a39b..c94d15ce0 100644 --- a/tests/_files/BankAccount-clover-line.xml +++ b/tests/_files/BankAccount-clover-line.xml @@ -2,23 +2,25 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/tests/_files/BankAccount-clover-path.xml b/tests/_files/BankAccount-clover-path.xml index c965427eb..4eb3d9b26 100644 --- a/tests/_files/BankAccount-clover-path.xml +++ b/tests/_files/BankAccount-clover-path.xml @@ -2,23 +2,25 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/class-with-anonymous-function-clover.xml index 4ff8a7ac8..d5b5099c1 100644 --- a/tests/_files/class-with-anonymous-function-clover.xml +++ b/tests/_files/class-with-anonymous-function-clover.xml @@ -2,20 +2,22 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/tests/_files/ignored-lines-clover.xml b/tests/_files/ignored-lines-clover.xml index a064f7407..7c022746a 100644 --- a/tests/_files/ignored-lines-clover.xml +++ b/tests/_files/ignored-lines-clover.xml @@ -2,15 +2,17 @@ - - - - - - - - - - + + + + + + + + + + + + From 9442bc740238f5fe5d7ee4077253850173e78c53 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 08:53:55 +0200 Subject: [PATCH 10/21] Ignore for now, see https://github.com/sebastianbergmann/php-code-coverage/pull/1080#issuecomment-2900005969 --- tests/_files/clover.xsd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/_files/clover.xsd b/tests/_files/clover.xsd index 3597fa68e..3b41fac49 100644 --- a/tests/_files/clover.xsd +++ b/tests/_files/clover.xsd @@ -11,7 +11,7 @@ - + From 30ef16c7fa7dd0305444d9ef87f824083be39a84 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 14:02:47 +0200 Subject: [PATCH 11/21] Set complexity attribute on the element under --- src/Node/AbstractNode.php | 18 ++++++++++++++++++ src/Report/Clover.php | 1 + tests/_files/BankAccount-clover-line.xml | 2 +- tests/_files/BankAccount-clover-path.xml | 2 +- .../class-with-anonymous-function-clover.xml | 2 +- tests/_files/ignored-lines-clover.xml | 2 +- 6 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Node/AbstractNode.php b/src/Node/AbstractNode.php index 2cee547f9..7e82a3daf 100644 --- a/src/Node/AbstractNode.php +++ b/src/Node/AbstractNode.php @@ -178,6 +178,24 @@ public function numberOfTestedFunctionsAndMethods(): int return $this->numberOfTestedFunctions() + $this->numberOfTestedMethods(); } + /** + * @return non-negative-int + */ + public function cyclomaticComplexity(): int + { + $ccn = 0; + + foreach ($this->classesAndTraits() as $classLike) { + $ccn += $classLike['ccn']; + } + + foreach ($this->functions() as $function) { + $ccn += $function['ccn']; + } + + return $ccn; + } + /** * @return array */ diff --git a/src/Report/Clover.php b/src/Report/Clover.php index 7270a82ae..1ef69aad9 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -206,6 +206,7 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlMetrics->setAttribute('classes', (string) $report->numberOfClassesAndTraits()); $xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods()); $xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods()); + $xmlMetrics->setAttribute('complexity', (string) $report->cyclomaticComplexity()); $xmlMetrics->setAttribute('conditionals', (string) $report->numberOfExecutableBranches()); $xmlMetrics->setAttribute('coveredconditionals', (string) $report->numberOfExecutedBranches()); $xmlMetrics->setAttribute('statements', (string) $report->numberOfExecutableLines()); diff --git a/tests/_files/BankAccount-clover-line.xml b/tests/_files/BankAccount-clover-line.xml index c94d15ce0..3fb9dbf8f 100644 --- a/tests/_files/BankAccount-clover-line.xml +++ b/tests/_files/BankAccount-clover-line.xml @@ -1,7 +1,7 @@ - + diff --git a/tests/_files/BankAccount-clover-path.xml b/tests/_files/BankAccount-clover-path.xml index 4eb3d9b26..99ed5c7ad 100644 --- a/tests/_files/BankAccount-clover-path.xml +++ b/tests/_files/BankAccount-clover-path.xml @@ -1,7 +1,7 @@ - + diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/class-with-anonymous-function-clover.xml index d5b5099c1..3b9d9dea3 100644 --- a/tests/_files/class-with-anonymous-function-clover.xml +++ b/tests/_files/class-with-anonymous-function-clover.xml @@ -1,7 +1,7 @@ - + diff --git a/tests/_files/ignored-lines-clover.xml b/tests/_files/ignored-lines-clover.xml index 7c022746a..8f329f637 100644 --- a/tests/_files/ignored-lines-clover.xml +++ b/tests/_files/ignored-lines-clover.xml @@ -1,7 +1,7 @@ - + From 364b23263db814fc6281f4547a2da681b96aebeb Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 14:25:10 +0200 Subject: [PATCH 12/21] Narrow type --- src/Report/Clover.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index 1ef69aad9..39ff0e3bb 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -20,6 +20,7 @@ use function str_contains; use function time; use DOMDocument; +use DOMElement; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Node\File; use SebastianBergmann\CodeCoverage\Util\Filesystem; @@ -52,6 +53,7 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlCoverage->appendChild($xmlProject); + /** @var array $packages */ $packages = []; $report = $coverage->getReport(); From 668aafa00c01ef7a1c584a2f8e01ff0e4527452d Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 14:25:33 +0200 Subject: [PATCH 13/21] - Use consistent order for attributes on elements - Set complexity attribute on the element under - Generate element as first child of element --- src/Report/Clover.php | 44 ++++++++++++------- tests/_files/BankAccount-clover-line.xml | 7 +-- tests/_files/BankAccount-clover-path.xml | 7 +-- .../class-with-anonymous-function-clover.xml | 7 +-- tests/_files/ignored-lines-clover.xml | 9 ++-- 5 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index 39ff0e3bb..496579a51 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -123,14 +123,14 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlMetrics = $xmlDocument->createElement('metrics'); $xmlMetrics->setAttribute('complexity', (string) $class['ccn']); - $xmlMetrics->setAttribute('methods', (string) $classMethods); - $xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods); + $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class['executableBranches'])); + $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class['executedBranches'])); $xmlMetrics->setAttribute('conditionals', (string) $class['executableBranches']); $xmlMetrics->setAttribute('coveredconditionals', (string) $class['executedBranches']); $xmlMetrics->setAttribute('statements', (string) $classStatements); $xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements); - $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class['executableBranches'])); - $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class['executedBranches'])); + $xmlMetrics->setAttribute('methods', (string) $classMethods); + $xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods); $xmlClass->insertBefore($xmlMetrics, $xmlClass->firstChild); } @@ -177,22 +177,34 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode()); $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode()); $xmlMetrics->setAttribute('classes', (string) $item->numberOfClassesAndTraits()); - $xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods()); - $xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods()); + $xmlMetrics->setAttribute('complexity', (string) $item->cyclomaticComplexity()); + $xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); + $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); $xmlMetrics->setAttribute('conditionals', (string) $item->numberOfExecutableBranches()); $xmlMetrics->setAttribute('coveredconditionals', (string) $item->numberOfExecutedBranches()); $xmlMetrics->setAttribute('statements', (string) $item->numberOfExecutableLines()); $xmlMetrics->setAttribute('coveredstatements', (string) $item->numberOfExecutedLines()); - $xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); - $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); + $xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods()); + $xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods()); $xmlFile->insertBefore($xmlMetrics, $xmlFile->firstChild); if (!isset($packages[$namespace])) { - $packages[$namespace] = $xmlDocument->createElement( - 'package', - ); - + $packages[$namespace] = $xmlDocument->createElement('package'); $packages[$namespace]->setAttribute('name', $namespace); + + $xmlPackageMetrics = $xmlDocument->createElement('metrics'); + // @todo Set attributes to actual values + $xmlPackageMetrics->setAttribute('complexity', '0'); + $xmlPackageMetrics->setAttribute('elements', '0'); + $xmlPackageMetrics->setAttribute('coveredelements', '0'); + $xmlPackageMetrics->setAttribute('conditionals', '0'); + $xmlPackageMetrics->setAttribute('coveredconditionals', '0'); + $xmlPackageMetrics->setAttribute('statements', '0'); + $xmlPackageMetrics->setAttribute('coveredstatements', '0'); + $xmlPackageMetrics->setAttribute('methods', '0'); + $xmlPackageMetrics->setAttribute('coveredmethods', '0'); + $packages[$namespace]->appendChild($xmlPackageMetrics); + $xmlProject->appendChild($packages[$namespace]); } @@ -206,15 +218,15 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode()); $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode()); $xmlMetrics->setAttribute('classes', (string) $report->numberOfClassesAndTraits()); - $xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods()); - $xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods()); $xmlMetrics->setAttribute('complexity', (string) $report->cyclomaticComplexity()); + $xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches())); + $xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches())); $xmlMetrics->setAttribute('conditionals', (string) $report->numberOfExecutableBranches()); $xmlMetrics->setAttribute('coveredconditionals', (string) $report->numberOfExecutedBranches()); $xmlMetrics->setAttribute('statements', (string) $report->numberOfExecutableLines()); $xmlMetrics->setAttribute('coveredstatements', (string) $report->numberOfExecutedLines()); - $xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches())); - $xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches())); + $xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods()); + $xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods()); $xmlProject->insertBefore($xmlMetrics, $xmlProject->firstChild); $buffer = $xmlDocument->saveXML(); diff --git a/tests/_files/BankAccount-clover-line.xml b/tests/_files/BankAccount-clover-line.xml index 3fb9dbf8f..375da13f0 100644 --- a/tests/_files/BankAccount-clover-line.xml +++ b/tests/_files/BankAccount-clover-line.xml @@ -1,12 +1,13 @@ - + + - + - + diff --git a/tests/_files/BankAccount-clover-path.xml b/tests/_files/BankAccount-clover-path.xml index 99ed5c7ad..368ea1010 100644 --- a/tests/_files/BankAccount-clover-path.xml +++ b/tests/_files/BankAccount-clover-path.xml @@ -1,12 +1,13 @@ - + + - + - + diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/class-with-anonymous-function-clover.xml index 3b9d9dea3..9e1db1666 100644 --- a/tests/_files/class-with-anonymous-function-clover.xml +++ b/tests/_files/class-with-anonymous-function-clover.xml @@ -1,12 +1,13 @@ - + + - + - + diff --git a/tests/_files/ignored-lines-clover.xml b/tests/_files/ignored-lines-clover.xml index 8f329f637..037adcbb0 100644 --- a/tests/_files/ignored-lines-clover.xml +++ b/tests/_files/ignored-lines-clover.xml @@ -1,15 +1,16 @@ - + + - + - + - + From 1a7d4b697d73364c3d8611bae2c1299a3b52d271 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 14:30:53 +0200 Subject: [PATCH 14/21] Remove namespace attribute from element --- src/Report/Clover.php | 1 - tests/_files/BankAccount-clover-line.xml | 2 +- tests/_files/BankAccount-clover-path.xml | 2 +- tests/_files/class-with-anonymous-function-clover.xml | 2 +- tests/_files/ignored-lines-clover.xml | 4 ++-- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index 496579a51..6daa6a224 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -117,7 +117,6 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlClass = $xmlDocument->createElement('class'); $xmlClass->setAttribute('name', $className); - $xmlClass->setAttribute('namespace', $namespace); $xmlFile->appendChild($xmlClass); diff --git a/tests/_files/BankAccount-clover-line.xml b/tests/_files/BankAccount-clover-line.xml index 375da13f0..9ae255f47 100644 --- a/tests/_files/BankAccount-clover-line.xml +++ b/tests/_files/BankAccount-clover-line.xml @@ -6,7 +6,7 @@ - + diff --git a/tests/_files/BankAccount-clover-path.xml b/tests/_files/BankAccount-clover-path.xml index 368ea1010..3d324ad71 100644 --- a/tests/_files/BankAccount-clover-path.xml +++ b/tests/_files/BankAccount-clover-path.xml @@ -6,7 +6,7 @@ - + diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/class-with-anonymous-function-clover.xml index 9e1db1666..a235096a5 100644 --- a/tests/_files/class-with-anonymous-function-clover.xml +++ b/tests/_files/class-with-anonymous-function-clover.xml @@ -6,7 +6,7 @@ - + diff --git a/tests/_files/ignored-lines-clover.xml b/tests/_files/ignored-lines-clover.xml index 037adcbb0..a6db0bc6e 100644 --- a/tests/_files/ignored-lines-clover.xml +++ b/tests/_files/ignored-lines-clover.xml @@ -6,10 +6,10 @@ - + - + From 5b619a7ec572c9ab668ca782ff3bed6fdff28a55 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 14:37:39 +0200 Subject: [PATCH 15/21] Remove name and crap attributes from element --- src/Report/Clover.php | 10 ---------- tests/_files/BankAccount-clover-line.xml | 8 ++++---- tests/_files/BankAccount-clover-path.xml | 8 ++++---- tests/_files/class-with-anonymous-function-clover.xml | 2 +- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index 6daa6a224..4bfbc445d 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -108,10 +108,8 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $lines[$method['startLine']] = [ 'ccn' => $method['ccn'], 'count' => $methodCount, - 'crap' => $method['crap'], 'type' => 'method', 'visibility' => $method['visibility'], - 'name' => $methodName, ]; } @@ -150,10 +148,6 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlLine->setAttribute('num', (string) $line); $xmlLine->setAttribute('type', $data['type']); - if (isset($data['name'])) { - $xmlLine->setAttribute('name', $data['name']); - } - if (isset($data['visibility'])) { $xmlLine->setAttribute('visibility', $data['visibility']); } @@ -162,10 +156,6 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlLine->setAttribute('complexity', (string) $data['ccn']); } - if (isset($data['crap'])) { - $xmlLine->setAttribute('crap', (string) $data['crap']); - } - $xmlLine->setAttribute('count', (string) $data['count']); $xmlFile->appendChild($xmlLine); } diff --git a/tests/_files/BankAccount-clover-line.xml b/tests/_files/BankAccount-clover-line.xml index 9ae255f47..0d8d8dc19 100644 --- a/tests/_files/BankAccount-clover-line.xml +++ b/tests/_files/BankAccount-clover-line.xml @@ -9,16 +9,16 @@ - + - + - + - + diff --git a/tests/_files/BankAccount-clover-path.xml b/tests/_files/BankAccount-clover-path.xml index 3d324ad71..417065154 100644 --- a/tests/_files/BankAccount-clover-path.xml +++ b/tests/_files/BankAccount-clover-path.xml @@ -9,16 +9,16 @@ - + - + - + - + diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/class-with-anonymous-function-clover.xml index a235096a5..f8b17a135 100644 --- a/tests/_files/class-with-anonymous-function-clover.xml +++ b/tests/_files/class-with-anonymous-function-clover.xml @@ -9,7 +9,7 @@ - + From 32d33df3a2d6cd3b9eae6ada587eaffb110c39d6 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 14:44:20 +0200 Subject: [PATCH 16/21] Fix CS/WS issue --- src/Report/Clover.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index 4bfbc445d..80d6c66dc 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -137,7 +137,8 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string } $lines[$line] = [ - 'count' => count($data), 'type' => 'stmt', + 'count' => count($data), + 'type' => 'stmt', ]; } From 9e1069939350d57f06614783138c7a597309694e Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 14:44:53 +0200 Subject: [PATCH 17/21] Set signature attribute on the element (and reorder attributes to match XSD) --- src/Report/Clover.php | 14 ++++++++++---- tests/_files/BankAccount-clover-line.xml | 8 ++++---- tests/_files/BankAccount-clover-path.xml | 8 ++++---- .../class-with-anonymous-function-clover.xml | 2 +- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index 80d6c66dc..87051747a 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -109,6 +109,7 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string 'ccn' => $method['ccn'], 'count' => $methodCount, 'type' => 'method', + 'signature' => $method['signature'], 'visibility' => $method['visibility'], ]; } @@ -149,15 +150,20 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlLine->setAttribute('num', (string) $line); $xmlLine->setAttribute('type', $data['type']); - if (isset($data['visibility'])) { - $xmlLine->setAttribute('visibility', $data['visibility']); - } - if (isset($data['ccn'])) { $xmlLine->setAttribute('complexity', (string) $data['ccn']); } $xmlLine->setAttribute('count', (string) $data['count']); + + if (isset($data['signature'])) { + $xmlLine->setAttribute('signature', $data['signature']); + } + + if (isset($data['visibility'])) { + $xmlLine->setAttribute('visibility', $data['visibility']); + } + $xmlFile->appendChild($xmlLine); } diff --git a/tests/_files/BankAccount-clover-line.xml b/tests/_files/BankAccount-clover-line.xml index 0d8d8dc19..16cf48650 100644 --- a/tests/_files/BankAccount-clover-line.xml +++ b/tests/_files/BankAccount-clover-line.xml @@ -9,16 +9,16 @@ - + - + - + - + diff --git a/tests/_files/BankAccount-clover-path.xml b/tests/_files/BankAccount-clover-path.xml index 417065154..25b976db4 100644 --- a/tests/_files/BankAccount-clover-path.xml +++ b/tests/_files/BankAccount-clover-path.xml @@ -9,16 +9,16 @@ - + - + - + - + diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/class-with-anonymous-function-clover.xml index f8b17a135..03f666b33 100644 --- a/tests/_files/class-with-anonymous-function-clover.xml +++ b/tests/_files/class-with-anonymous-function-clover.xml @@ -9,7 +9,7 @@ - + From 1c61bb3bf6dd7d4f5b3ffa7aef90acce87cbe394 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 14:56:36 +0200 Subject: [PATCH 18/21] Set attributes of element under to actual values --- src/Report/Clover.php | 16 +++++++++++++++- tests/_files/BankAccount-clover-line.xml | 2 +- tests/_files/BankAccount-clover-path.xml | 2 +- .../class-with-anonymous-function-clover.xml | 2 +- tests/_files/ignored-lines-clover.xml | 2 +- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index 87051747a..2d971056c 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -9,6 +9,7 @@ */ namespace SebastianBergmann\CodeCoverage\Report; +use function assert; use function basename; use function count; use function dirname; @@ -189,7 +190,6 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $packages[$namespace]->setAttribute('name', $namespace); $xmlPackageMetrics = $xmlDocument->createElement('metrics'); - // @todo Set attributes to actual values $xmlPackageMetrics->setAttribute('complexity', '0'); $xmlPackageMetrics->setAttribute('elements', '0'); $xmlPackageMetrics->setAttribute('coveredelements', '0'); @@ -204,6 +204,20 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlProject->appendChild($packages[$namespace]); } + $xmlPackageMetrics = $packages[$namespace]->firstChild; + + assert($xmlPackageMetrics instanceof DOMElement); + + $xmlPackageMetrics->setAttribute('complexity', (string) ((int) $xmlPackageMetrics->getAttribute('complexity') + $item->cyclomaticComplexity())); + $xmlPackageMetrics->setAttribute('elements', (string) ((int) $xmlPackageMetrics->getAttribute('elements') + $item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); + $xmlPackageMetrics->setAttribute('coveredelements', (string) ((int) $xmlPackageMetrics->getAttribute('coveredelements') + $item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); + $xmlPackageMetrics->setAttribute('conditionals', (string) ((int) $xmlPackageMetrics->getAttribute('conditionals') + $item->numberOfExecutableBranches())); + $xmlPackageMetrics->setAttribute('coveredconditionals', (string) ((int) $xmlPackageMetrics->getAttribute('coveredconditionals') + $item->numberOfExecutedBranches())); + $xmlPackageMetrics->setAttribute('statements', (string) ((int) $xmlPackageMetrics->getAttribute('statements') + $item->numberOfExecutableLines())); + $xmlPackageMetrics->setAttribute('coveredstatements', (string) ((int) $xmlPackageMetrics->getAttribute('coveredstatements') + $item->numberOfExecutedLines())); + $xmlPackageMetrics->setAttribute('methods', (string) ((int) $xmlPackageMetrics->getAttribute('methods') + $item->numberOfMethods())); + $xmlPackageMetrics->setAttribute('coveredmethods', (string) ((int) $xmlPackageMetrics->getAttribute('coveredmethods') + $item->numberOfTestedMethods())); + $packages[$namespace]->appendChild($xmlFile); } diff --git a/tests/_files/BankAccount-clover-line.xml b/tests/_files/BankAccount-clover-line.xml index 16cf48650..eef39f2aa 100644 --- a/tests/_files/BankAccount-clover-line.xml +++ b/tests/_files/BankAccount-clover-line.xml @@ -3,7 +3,7 @@ - + diff --git a/tests/_files/BankAccount-clover-path.xml b/tests/_files/BankAccount-clover-path.xml index 25b976db4..2612cb850 100644 --- a/tests/_files/BankAccount-clover-path.xml +++ b/tests/_files/BankAccount-clover-path.xml @@ -3,7 +3,7 @@ - + diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/class-with-anonymous-function-clover.xml index 03f666b33..2ec261e6c 100644 --- a/tests/_files/class-with-anonymous-function-clover.xml +++ b/tests/_files/class-with-anonymous-function-clover.xml @@ -3,7 +3,7 @@ - + diff --git a/tests/_files/ignored-lines-clover.xml b/tests/_files/ignored-lines-clover.xml index a6db0bc6e..063db4b79 100644 --- a/tests/_files/ignored-lines-clover.xml +++ b/tests/_files/ignored-lines-clover.xml @@ -3,7 +3,7 @@ - + From d75e902d618380d24faaed429d34f55f63f6e149 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Thu, 22 May 2025 15:08:30 +0200 Subject: [PATCH 19/21] Set attribute name of element to unqualified class name --- src/Report/Clover.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Report/Clover.php b/src/Report/Clover.php index 2d971056c..d271430fd 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -19,6 +19,7 @@ use function max; use function range; use function str_contains; +use function str_replace; use function time; use DOMDocument; use DOMElement; @@ -116,7 +117,7 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string } $xmlClass = $xmlDocument->createElement('class'); - $xmlClass->setAttribute('name', $className); + $xmlClass->setAttribute('name', str_replace($class['namespace'] . '\\', '', $className)); $xmlFile->appendChild($xmlClass); From b78c11043eac9a1a66ec54569e967b7b8d0e9c54 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Fri, 23 May 2025 13:57:52 +0200 Subject: [PATCH 20/21] Keep Report\Clover as-is and introduce new Report\OpenClover for reporter that generates Clover XML that validates against OpenClover's XML schema definition --- src/Report/Clover.php | 118 ++++---- src/Report/OpenClover.php | 257 ++++++++++++++++++ .../_files/Report/Clover/BankAccount-line.xml | 24 ++ .../_files/Report/Clover/BankAccount-path.xml | 24 ++ .../Clover/class-with-anonymous-function.xml | 21 ++ tests/_files/Report/Clover/ignored-lines.xml | 16 ++ .../OpenClover/BankAccount-line.xml} | 0 .../OpenClover/BankAccount-path.xml} | 0 .../class-with-anonymous-function.xml} | 0 .../OpenClover/ignored-lines.xml} | 0 tests/tests/Report/CloverTest.php | 57 +--- tests/tests/Report/OpenCloverTest.php | 98 +++++++ 12 files changed, 495 insertions(+), 120 deletions(-) create mode 100644 src/Report/OpenClover.php create mode 100644 tests/_files/Report/Clover/BankAccount-line.xml create mode 100644 tests/_files/Report/Clover/BankAccount-path.xml create mode 100644 tests/_files/Report/Clover/class-with-anonymous-function.xml create mode 100644 tests/_files/Report/Clover/ignored-lines.xml rename tests/_files/{BankAccount-clover-line.xml => Report/OpenClover/BankAccount-line.xml} (100%) rename tests/_files/{BankAccount-clover-path.xml => Report/OpenClover/BankAccount-path.xml} (100%) rename tests/_files/{class-with-anonymous-function-clover.xml => Report/OpenClover/class-with-anonymous-function.xml} (100%) rename tests/_files/{ignored-lines-clover.xml => Report/OpenClover/ignored-lines.xml} (100%) create mode 100644 tests/tests/Report/OpenCloverTest.php diff --git a/src/Report/Clover.php b/src/Report/Clover.php index d271430fd..a5f1c09e6 100644 --- a/src/Report/Clover.php +++ b/src/Report/Clover.php @@ -9,8 +9,6 @@ */ namespace SebastianBergmann\CodeCoverage\Report; -use function assert; -use function basename; use function count; use function dirname; use function file_put_contents; @@ -19,14 +17,11 @@ use function max; use function range; use function str_contains; -use function str_replace; use function time; use DOMDocument; -use DOMElement; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Node\File; use SebastianBergmann\CodeCoverage\Util\Filesystem; -use SebastianBergmann\CodeCoverage\Version; use SebastianBergmann\CodeCoverage\WriteOperationFailedException; final class Clover @@ -42,7 +37,6 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlDocument->formatOutput = true; $xmlCoverage = $xmlDocument->createElement('coverage'); - $xmlCoverage->setAttribute('clover', Version::id()); $xmlCoverage->setAttribute('generated', $time); $xmlDocument->appendChild($xmlCoverage); @@ -55,7 +49,6 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlCoverage->appendChild($xmlProject); - /** @var array $packages */ $packages = []; $report = $coverage->getReport(); @@ -64,9 +57,10 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string continue; } + /* @var File $item */ + $xmlFile = $xmlDocument->createElement('file'); - $xmlFile->setAttribute('name', basename($item->pathAsString())); - $xmlFile->setAttribute('path', $item->pathAsString()); + $xmlFile->setAttribute('name', $item->pathAsString()); $classes = $item->classesAndTraits(); $coverageData = $item->lineCoverageData(); @@ -110,28 +104,30 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $lines[$method['startLine']] = [ 'ccn' => $method['ccn'], 'count' => $methodCount, + 'crap' => $method['crap'], 'type' => 'method', - 'signature' => $method['signature'], 'visibility' => $method['visibility'], + 'name' => $methodName, ]; } $xmlClass = $xmlDocument->createElement('class'); - $xmlClass->setAttribute('name', str_replace($class['namespace'] . '\\', '', $className)); + $xmlClass->setAttribute('name', $className); + $xmlClass->setAttribute('namespace', $namespace); $xmlFile->appendChild($xmlClass); $xmlMetrics = $xmlDocument->createElement('metrics'); $xmlMetrics->setAttribute('complexity', (string) $class['ccn']); - $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class['executableBranches'])); - $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class['executedBranches'])); + $xmlMetrics->setAttribute('methods', (string) $classMethods); + $xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods); $xmlMetrics->setAttribute('conditionals', (string) $class['executableBranches']); $xmlMetrics->setAttribute('coveredconditionals', (string) $class['executedBranches']); $xmlMetrics->setAttribute('statements', (string) $classStatements); $xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements); - $xmlMetrics->setAttribute('methods', (string) $classMethods); - $xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods); - $xmlClass->insertBefore($xmlMetrics, $xmlClass->firstChild); + $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class['executableBranches'])); + $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class['executedBranches'])); + $xmlClass->appendChild($xmlMetrics); } foreach ($coverageData as $line => $data) { @@ -140,8 +136,7 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string } $lines[$line] = [ - 'count' => count($data), - 'type' => 'stmt', + 'count' => count($data), 'type' => 'stmt', ]; } @@ -152,20 +147,23 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlLine->setAttribute('num', (string) $line); $xmlLine->setAttribute('type', $data['type']); - if (isset($data['ccn'])) { - $xmlLine->setAttribute('complexity', (string) $data['ccn']); + if (isset($data['name'])) { + $xmlLine->setAttribute('name', $data['name']); } - $xmlLine->setAttribute('count', (string) $data['count']); + if (isset($data['visibility'])) { + $xmlLine->setAttribute('visibility', $data['visibility']); + } - if (isset($data['signature'])) { - $xmlLine->setAttribute('signature', $data['signature']); + if (isset($data['ccn'])) { + $xmlLine->setAttribute('complexity', (string) $data['ccn']); } - if (isset($data['visibility'])) { - $xmlLine->setAttribute('visibility', $data['visibility']); + if (isset($data['crap'])) { + $xmlLine->setAttribute('crap', (string) $data['crap']); } + $xmlLine->setAttribute('count', (string) $data['count']); $xmlFile->appendChild($xmlLine); } @@ -175,51 +173,30 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode()); $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode()); $xmlMetrics->setAttribute('classes', (string) $item->numberOfClassesAndTraits()); - $xmlMetrics->setAttribute('complexity', (string) $item->cyclomaticComplexity()); - $xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); - $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); + $xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods()); + $xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods()); $xmlMetrics->setAttribute('conditionals', (string) $item->numberOfExecutableBranches()); $xmlMetrics->setAttribute('coveredconditionals', (string) $item->numberOfExecutedBranches()); $xmlMetrics->setAttribute('statements', (string) $item->numberOfExecutableLines()); $xmlMetrics->setAttribute('coveredstatements', (string) $item->numberOfExecutedLines()); - $xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods()); - $xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods()); - $xmlFile->insertBefore($xmlMetrics, $xmlFile->firstChild); - - if (!isset($packages[$namespace])) { - $packages[$namespace] = $xmlDocument->createElement('package'); - $packages[$namespace]->setAttribute('name', $namespace); - - $xmlPackageMetrics = $xmlDocument->createElement('metrics'); - $xmlPackageMetrics->setAttribute('complexity', '0'); - $xmlPackageMetrics->setAttribute('elements', '0'); - $xmlPackageMetrics->setAttribute('coveredelements', '0'); - $xmlPackageMetrics->setAttribute('conditionals', '0'); - $xmlPackageMetrics->setAttribute('coveredconditionals', '0'); - $xmlPackageMetrics->setAttribute('statements', '0'); - $xmlPackageMetrics->setAttribute('coveredstatements', '0'); - $xmlPackageMetrics->setAttribute('methods', '0'); - $xmlPackageMetrics->setAttribute('coveredmethods', '0'); - $packages[$namespace]->appendChild($xmlPackageMetrics); - - $xmlProject->appendChild($packages[$namespace]); - } - - $xmlPackageMetrics = $packages[$namespace]->firstChild; - - assert($xmlPackageMetrics instanceof DOMElement); - - $xmlPackageMetrics->setAttribute('complexity', (string) ((int) $xmlPackageMetrics->getAttribute('complexity') + $item->cyclomaticComplexity())); - $xmlPackageMetrics->setAttribute('elements', (string) ((int) $xmlPackageMetrics->getAttribute('elements') + $item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); - $xmlPackageMetrics->setAttribute('coveredelements', (string) ((int) $xmlPackageMetrics->getAttribute('coveredelements') + $item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); - $xmlPackageMetrics->setAttribute('conditionals', (string) ((int) $xmlPackageMetrics->getAttribute('conditionals') + $item->numberOfExecutableBranches())); - $xmlPackageMetrics->setAttribute('coveredconditionals', (string) ((int) $xmlPackageMetrics->getAttribute('coveredconditionals') + $item->numberOfExecutedBranches())); - $xmlPackageMetrics->setAttribute('statements', (string) ((int) $xmlPackageMetrics->getAttribute('statements') + $item->numberOfExecutableLines())); - $xmlPackageMetrics->setAttribute('coveredstatements', (string) ((int) $xmlPackageMetrics->getAttribute('coveredstatements') + $item->numberOfExecutedLines())); - $xmlPackageMetrics->setAttribute('methods', (string) ((int) $xmlPackageMetrics->getAttribute('methods') + $item->numberOfMethods())); - $xmlPackageMetrics->setAttribute('coveredmethods', (string) ((int) $xmlPackageMetrics->getAttribute('coveredmethods') + $item->numberOfTestedMethods())); + $xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); + $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); + $xmlFile->appendChild($xmlMetrics); + + if ($namespace === 'global') { + $xmlProject->appendChild($xmlFile); + } else { + if (!isset($packages[$namespace])) { + $packages[$namespace] = $xmlDocument->createElement( + 'package', + ); + + $packages[$namespace]->setAttribute('name', $namespace); + $xmlProject->appendChild($packages[$namespace]); + } - $packages[$namespace]->appendChild($xmlFile); + $packages[$namespace]->appendChild($xmlFile); + } } $linesOfCode = $report->linesOfCode(); @@ -229,16 +206,15 @@ public function process(CodeCoverage $coverage, ?string $target = null, ?string $xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode()); $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode()); $xmlMetrics->setAttribute('classes', (string) $report->numberOfClassesAndTraits()); - $xmlMetrics->setAttribute('complexity', (string) $report->cyclomaticComplexity()); - $xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches())); - $xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches())); + $xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods()); + $xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods()); $xmlMetrics->setAttribute('conditionals', (string) $report->numberOfExecutableBranches()); $xmlMetrics->setAttribute('coveredconditionals', (string) $report->numberOfExecutedBranches()); $xmlMetrics->setAttribute('statements', (string) $report->numberOfExecutableLines()); $xmlMetrics->setAttribute('coveredstatements', (string) $report->numberOfExecutedLines()); - $xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods()); - $xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods()); - $xmlProject->insertBefore($xmlMetrics, $xmlProject->firstChild); + $xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches())); + $xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches())); + $xmlProject->appendChild($xmlMetrics); $buffer = $xmlDocument->saveXML(); diff --git a/src/Report/OpenClover.php b/src/Report/OpenClover.php new file mode 100644 index 000000000..042132b33 --- /dev/null +++ b/src/Report/OpenClover.php @@ -0,0 +1,257 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use function assert; +use function basename; +use function count; +use function dirname; +use function file_put_contents; +use function is_string; +use function ksort; +use function max; +use function range; +use function str_contains; +use function str_replace; +use function time; +use DOMDocument; +use DOMElement; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Node\File; +use SebastianBergmann\CodeCoverage\Util\Filesystem; +use SebastianBergmann\CodeCoverage\Version; +use SebastianBergmann\CodeCoverage\WriteOperationFailedException; + +final class OpenClover +{ + /** + * @throws WriteOperationFailedException + */ + public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string + { + $time = (string) time(); + + $xmlDocument = new DOMDocument('1.0', 'UTF-8'); + $xmlDocument->formatOutput = true; + + $xmlCoverage = $xmlDocument->createElement('coverage'); + $xmlCoverage->setAttribute('clover', Version::id()); + $xmlCoverage->setAttribute('generated', $time); + $xmlDocument->appendChild($xmlCoverage); + + $xmlProject = $xmlDocument->createElement('project'); + $xmlProject->setAttribute('timestamp', $time); + + if (is_string($name)) { + $xmlProject->setAttribute('name', $name); + } + + $xmlCoverage->appendChild($xmlProject); + + /** @var array $packages */ + $packages = []; + $report = $coverage->getReport(); + + foreach ($report as $item) { + if (!$item instanceof File) { + continue; + } + + $xmlFile = $xmlDocument->createElement('file'); + $xmlFile->setAttribute('name', basename($item->pathAsString())); + $xmlFile->setAttribute('path', $item->pathAsString()); + + $classes = $item->classesAndTraits(); + $coverageData = $item->lineCoverageData(); + $lines = []; + $namespace = 'global'; + + foreach ($classes as $className => $class) { + $classStatements = 0; + $coveredClassStatements = 0; + $coveredMethods = 0; + $classMethods = 0; + + // Assumption: one namespace per file + if ($class['namespace'] !== '') { + $namespace = $class['namespace']; + } + + foreach ($class['methods'] as $methodName => $method) { + /** @phpstan-ignore equal.notAllowed */ + if ($method['executableLines'] == 0) { + continue; + } + + $classMethods++; + $classStatements += $method['executableLines']; + $coveredClassStatements += $method['executedLines']; + + /** @phpstan-ignore equal.notAllowed */ + if ($method['coverage'] == 100) { + $coveredMethods++; + } + + $methodCount = 0; + + foreach (range($method['startLine'], $method['endLine']) as $line) { + if (isset($coverageData[$line])) { + $methodCount = max($methodCount, count($coverageData[$line])); + } + } + + $lines[$method['startLine']] = [ + 'ccn' => $method['ccn'], + 'count' => $methodCount, + 'type' => 'method', + 'signature' => $method['signature'], + 'visibility' => $method['visibility'], + ]; + } + + $xmlClass = $xmlDocument->createElement('class'); + $xmlClass->setAttribute('name', str_replace($class['namespace'] . '\\', '', $className)); + + $xmlFile->appendChild($xmlClass); + + $xmlMetrics = $xmlDocument->createElement('metrics'); + $xmlMetrics->setAttribute('complexity', (string) $class['ccn']); + $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class['executableBranches'])); + $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class['executedBranches'])); + $xmlMetrics->setAttribute('conditionals', (string) $class['executableBranches']); + $xmlMetrics->setAttribute('coveredconditionals', (string) $class['executedBranches']); + $xmlMetrics->setAttribute('statements', (string) $classStatements); + $xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements); + $xmlMetrics->setAttribute('methods', (string) $classMethods); + $xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods); + $xmlClass->insertBefore($xmlMetrics, $xmlClass->firstChild); + } + + foreach ($coverageData as $line => $data) { + if ($data === null || isset($lines[$line])) { + continue; + } + + $lines[$line] = [ + 'count' => count($data), + 'type' => 'stmt', + ]; + } + + ksort($lines); + + foreach ($lines as $line => $data) { + $xmlLine = $xmlDocument->createElement('line'); + $xmlLine->setAttribute('num', (string) $line); + $xmlLine->setAttribute('type', $data['type']); + + if (isset($data['ccn'])) { + $xmlLine->setAttribute('complexity', (string) $data['ccn']); + } + + $xmlLine->setAttribute('count', (string) $data['count']); + + if (isset($data['signature'])) { + $xmlLine->setAttribute('signature', $data['signature']); + } + + if (isset($data['visibility'])) { + $xmlLine->setAttribute('visibility', $data['visibility']); + } + + $xmlFile->appendChild($xmlLine); + } + + $linesOfCode = $item->linesOfCode(); + + $xmlMetrics = $xmlDocument->createElement('metrics'); + $xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode()); + $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode()); + $xmlMetrics->setAttribute('classes', (string) $item->numberOfClassesAndTraits()); + $xmlMetrics->setAttribute('complexity', (string) $item->cyclomaticComplexity()); + $xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); + $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); + $xmlMetrics->setAttribute('conditionals', (string) $item->numberOfExecutableBranches()); + $xmlMetrics->setAttribute('coveredconditionals', (string) $item->numberOfExecutedBranches()); + $xmlMetrics->setAttribute('statements', (string) $item->numberOfExecutableLines()); + $xmlMetrics->setAttribute('coveredstatements', (string) $item->numberOfExecutedLines()); + $xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods()); + $xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods()); + $xmlFile->insertBefore($xmlMetrics, $xmlFile->firstChild); + + if (!isset($packages[$namespace])) { + $packages[$namespace] = $xmlDocument->createElement('package'); + $packages[$namespace]->setAttribute('name', $namespace); + + $xmlPackageMetrics = $xmlDocument->createElement('metrics'); + $xmlPackageMetrics->setAttribute('complexity', '0'); + $xmlPackageMetrics->setAttribute('elements', '0'); + $xmlPackageMetrics->setAttribute('coveredelements', '0'); + $xmlPackageMetrics->setAttribute('conditionals', '0'); + $xmlPackageMetrics->setAttribute('coveredconditionals', '0'); + $xmlPackageMetrics->setAttribute('statements', '0'); + $xmlPackageMetrics->setAttribute('coveredstatements', '0'); + $xmlPackageMetrics->setAttribute('methods', '0'); + $xmlPackageMetrics->setAttribute('coveredmethods', '0'); + $packages[$namespace]->appendChild($xmlPackageMetrics); + + $xmlProject->appendChild($packages[$namespace]); + } + + $xmlPackageMetrics = $packages[$namespace]->firstChild; + + assert($xmlPackageMetrics instanceof DOMElement); + + $xmlPackageMetrics->setAttribute('complexity', (string) ((int) $xmlPackageMetrics->getAttribute('complexity') + $item->cyclomaticComplexity())); + $xmlPackageMetrics->setAttribute('elements', (string) ((int) $xmlPackageMetrics->getAttribute('elements') + $item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); + $xmlPackageMetrics->setAttribute('coveredelements', (string) ((int) $xmlPackageMetrics->getAttribute('coveredelements') + $item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); + $xmlPackageMetrics->setAttribute('conditionals', (string) ((int) $xmlPackageMetrics->getAttribute('conditionals') + $item->numberOfExecutableBranches())); + $xmlPackageMetrics->setAttribute('coveredconditionals', (string) ((int) $xmlPackageMetrics->getAttribute('coveredconditionals') + $item->numberOfExecutedBranches())); + $xmlPackageMetrics->setAttribute('statements', (string) ((int) $xmlPackageMetrics->getAttribute('statements') + $item->numberOfExecutableLines())); + $xmlPackageMetrics->setAttribute('coveredstatements', (string) ((int) $xmlPackageMetrics->getAttribute('coveredstatements') + $item->numberOfExecutedLines())); + $xmlPackageMetrics->setAttribute('methods', (string) ((int) $xmlPackageMetrics->getAttribute('methods') + $item->numberOfMethods())); + $xmlPackageMetrics->setAttribute('coveredmethods', (string) ((int) $xmlPackageMetrics->getAttribute('coveredmethods') + $item->numberOfTestedMethods())); + + $packages[$namespace]->appendChild($xmlFile); + } + + $linesOfCode = $report->linesOfCode(); + + $xmlMetrics = $xmlDocument->createElement('metrics'); + $xmlMetrics->setAttribute('files', (string) count($report)); + $xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode()); + $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode()); + $xmlMetrics->setAttribute('classes', (string) $report->numberOfClassesAndTraits()); + $xmlMetrics->setAttribute('complexity', (string) $report->cyclomaticComplexity()); + $xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches())); + $xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches())); + $xmlMetrics->setAttribute('conditionals', (string) $report->numberOfExecutableBranches()); + $xmlMetrics->setAttribute('coveredconditionals', (string) $report->numberOfExecutedBranches()); + $xmlMetrics->setAttribute('statements', (string) $report->numberOfExecutableLines()); + $xmlMetrics->setAttribute('coveredstatements', (string) $report->numberOfExecutedLines()); + $xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods()); + $xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods()); + $xmlProject->insertBefore($xmlMetrics, $xmlProject->firstChild); + + $buffer = $xmlDocument->saveXML(); + + if ($target !== null) { + if (!str_contains($target, '://')) { + Filesystem::createDirectory(dirname($target)); + } + + if (@file_put_contents($target, $buffer) === false) { + throw new WriteOperationFailedException($target); + } + } + + return $buffer; + } +} diff --git a/tests/_files/Report/Clover/BankAccount-line.xml b/tests/_files/Report/Clover/BankAccount-line.xml new file mode 100644 index 000000000..9a6fca706 --- /dev/null +++ b/tests/_files/Report/Clover/BankAccount-line.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/_files/Report/Clover/BankAccount-path.xml b/tests/_files/Report/Clover/BankAccount-path.xml new file mode 100644 index 000000000..b49f4c915 --- /dev/null +++ b/tests/_files/Report/Clover/BankAccount-path.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/_files/Report/Clover/class-with-anonymous-function.xml b/tests/_files/Report/Clover/class-with-anonymous-function.xml new file mode 100644 index 000000000..34a84690a --- /dev/null +++ b/tests/_files/Report/Clover/class-with-anonymous-function.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/_files/Report/Clover/ignored-lines.xml b/tests/_files/Report/Clover/ignored-lines.xml new file mode 100644 index 000000000..39a32558a --- /dev/null +++ b/tests/_files/Report/Clover/ignored-lines.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tests/_files/BankAccount-clover-line.xml b/tests/_files/Report/OpenClover/BankAccount-line.xml similarity index 100% rename from tests/_files/BankAccount-clover-line.xml rename to tests/_files/Report/OpenClover/BankAccount-line.xml diff --git a/tests/_files/BankAccount-clover-path.xml b/tests/_files/Report/OpenClover/BankAccount-path.xml similarity index 100% rename from tests/_files/BankAccount-clover-path.xml rename to tests/_files/Report/OpenClover/BankAccount-path.xml diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/Report/OpenClover/class-with-anonymous-function.xml similarity index 100% rename from tests/_files/class-with-anonymous-function-clover.xml rename to tests/_files/Report/OpenClover/class-with-anonymous-function.xml diff --git a/tests/_files/ignored-lines-clover.xml b/tests/_files/Report/OpenClover/ignored-lines.xml similarity index 100% rename from tests/_files/ignored-lines-clover.xml rename to tests/_files/Report/OpenClover/ignored-lines.xml diff --git a/tests/tests/Report/CloverTest.php b/tests/tests/Report/CloverTest.php index 4df3f74bf..114642061 100644 --- a/tests/tests/Report/CloverTest.php +++ b/tests/tests/Report/CloverTest.php @@ -9,13 +9,6 @@ */ namespace SebastianBergmann\CodeCoverage\Report; -use const PHP_EOL; -use function libxml_clear_errors; -use function libxml_get_errors; -use function libxml_use_internal_errors; -use function sprintf; -use function trim; -use DOMDocument; use PHPUnit\Framework\Attributes\CoversClass; use SebastianBergmann\CodeCoverage\TestCase; @@ -26,8 +19,8 @@ public function testLineCoverageForBankAccountTest(): void { $clover = new Clover; - $this->assertAndValidate( - TEST_FILES_PATH . 'BankAccount-clover-line.xml', + $this->assertStringMatchesFormatFile( + TEST_FILES_PATH . 'Report/Clover/BankAccount-line.xml', $clover->process($this->getLineCoverageForBankAccount(), null, 'BankAccount'), ); } @@ -36,8 +29,8 @@ public function testPathCoverageForBankAccountTest(): void { $clover = new Clover; - $this->assertAndValidate( - TEST_FILES_PATH . 'BankAccount-clover-path.xml', + $this->assertStringMatchesFormatFile( + TEST_FILES_PATH . 'Report/Clover/BankAccount-path.xml', $clover->process($this->getPathCoverageForBankAccount(), null, 'BankAccount'), ); } @@ -46,8 +39,8 @@ public function testCloverForFileWithIgnoredLines(): void { $clover = new Clover; - $this->assertAndValidate( - TEST_FILES_PATH . 'ignored-lines-clover.xml', + $this->assertStringMatchesFormatFile( + TEST_FILES_PATH . 'Report/Clover/ignored-lines.xml', $clover->process($this->getCoverageForFileWithIgnoredLines()), ); } @@ -56,43 +49,9 @@ public function testCloverForClassWithAnonymousFunction(): void { $clover = new Clover; - $this->assertAndValidate( - TEST_FILES_PATH . 'class-with-anonymous-function-clover.xml', + $this->assertStringMatchesFormatFile( + TEST_FILES_PATH . 'Report/Clover/class-with-anonymous-function.xml', $clover->process($this->getCoverageForClassWithAnonymousFunction()), ); } - - /** - * @param non-empty-string $expectationFile - * @param non-empty-string $cloverXml - */ - private function assertAndValidate(string $expectationFile, string $cloverXml): void - { - $this->assertStringMatchesFormatFile($expectationFile, $cloverXml); - - libxml_use_internal_errors(true); - - $document = new DOMDocument; - $document->loadXML($cloverXml); - - if (!$document->schemaValidate(__DIR__ . '/../../_files/clover.xsd')) { - $buffer = 'Generated XML document does not validate against Clover schema:' . PHP_EOL . PHP_EOL; - - foreach (libxml_get_errors() as $error) { - $buffer .= sprintf( - '- Line %d: %s' . PHP_EOL, - $error->line, - trim($error->message), - ); - } - - $buffer .= PHP_EOL; - } - - libxml_clear_errors(); - - if (isset($buffer)) { - $this->fail($buffer); - } - } } diff --git a/tests/tests/Report/OpenCloverTest.php b/tests/tests/Report/OpenCloverTest.php new file mode 100644 index 000000000..371b47677 --- /dev/null +++ b/tests/tests/Report/OpenCloverTest.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use const PHP_EOL; +use function libxml_clear_errors; +use function libxml_get_errors; +use function libxml_use_internal_errors; +use function sprintf; +use function trim; +use DOMDocument; +use PHPUnit\Framework\Attributes\CoversClass; +use SebastianBergmann\CodeCoverage\TestCase; + +#[CoversClass(OpenClover::class)] +final class OpenCloverTest extends TestCase +{ + public function testLineCoverageForBankAccountTest(): void + { + $clover = new OpenClover; + + $this->assertAndValidate( + TEST_FILES_PATH . 'Report/OpenClover/BankAccount-line.xml', + $clover->process($this->getLineCoverageForBankAccount(), null, 'BankAccount'), + ); + } + + public function testPathCoverageForBankAccountTest(): void + { + $clover = new OpenClover; + + $this->assertAndValidate( + TEST_FILES_PATH . 'Report/OpenClover/BankAccount-path.xml', + $clover->process($this->getPathCoverageForBankAccount(), null, 'BankAccount'), + ); + } + + public function testCloverForFileWithIgnoredLines(): void + { + $clover = new OpenClover; + + $this->assertAndValidate( + TEST_FILES_PATH . 'Report/OpenClover/ignored-lines.xml', + $clover->process($this->getCoverageForFileWithIgnoredLines()), + ); + } + + public function testCloverForClassWithAnonymousFunction(): void + { + $clover = new OpenClover; + + $this->assertAndValidate( + TEST_FILES_PATH . 'Report/OpenClover/class-with-anonymous-function.xml', + $clover->process($this->getCoverageForClassWithAnonymousFunction()), + ); + } + + /** + * @param non-empty-string $expectationFile + * @param non-empty-string $cloverXml + */ + private function assertAndValidate(string $expectationFile, string $cloverXml): void + { + $this->assertStringMatchesFormatFile($expectationFile, $cloverXml); + + libxml_use_internal_errors(true); + + $document = new DOMDocument; + $document->loadXML($cloverXml); + + if (!$document->schemaValidate(__DIR__ . '/../../_files/clover.xsd')) { + $buffer = 'Generated XML document does not validate against Clover schema:' . PHP_EOL . PHP_EOL; + + foreach (libxml_get_errors() as $error) { + $buffer .= sprintf( + '- Line %d: %s' . PHP_EOL, + $error->line, + trim($error->message), + ); + } + + $buffer .= PHP_EOL; + } + + libxml_clear_errors(); + + if (isset($buffer)) { + $this->fail($buffer); + } + } +} From 7ea8837b2bccf4b14ac49df7d2a15ed3df9e649e Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Fri, 23 May 2025 14:05:24 +0200 Subject: [PATCH 21/21] Reorganize --- .../Cobertura/BankAccount-line.xml} | 0 .../Cobertura/BankAccount-path.xml} | 0 .../class-with-anonymous-function.xml} | 0 .../Cobertura/class-with-outside-function.xml} | 0 .../Cobertura/ignored-lines.xml} | 0 .../Crap4j/BankAccount.xml} | 0 .../Crap4j/class-with-anonymous-function.xml} | 0 .../Crap4j/ignored-lines.xml} | 0 .../_files/{ => Report/OpenClover}/clover.xsd | 0 .../Text/BankAccount-line.txt} | 0 .../Text/BankAccount-path.txt} | 0 .../Text/BankAccount-summary.txt} | 0 .../Text/BankAccountWithUncovered-line.txt} | 0 .../Text/BankAccountWithoutUncovered-line.txt} | 0 .../Text/NamespacedBankAccount-colors.txt} | 0 .../Text/NamespacedBankAccount.txt} | 0 .../Text/class-with-anonymous-function.txt} | 0 .../Text/ignored-lines.txt} | 0 tests/tests/Report/CoberturaTest.php | 10 +++++----- tests/tests/Report/Crap4jTest.php | 6 +++--- tests/tests/Report/OpenCloverTest.php | 2 +- tests/tests/Report/TextTest.php | 18 +++++++++--------- 22 files changed, 18 insertions(+), 18 deletions(-) rename tests/_files/{BankAccount-cobertura-line.xml => Report/Cobertura/BankAccount-line.xml} (100%) rename tests/_files/{BankAccount-cobertura-path.xml => Report/Cobertura/BankAccount-path.xml} (100%) rename tests/_files/{class-with-anonymous-function-cobertura.xml => Report/Cobertura/class-with-anonymous-function.xml} (100%) rename tests/_files/{class-with-outside-function-cobertura.xml => Report/Cobertura/class-with-outside-function.xml} (100%) rename tests/_files/{ignored-lines-cobertura.xml => Report/Cobertura/ignored-lines.xml} (100%) rename tests/_files/{BankAccount-crap4j.xml => Report/Crap4j/BankAccount.xml} (100%) rename tests/_files/{class-with-anonymous-function-crap4j.xml => Report/Crap4j/class-with-anonymous-function.xml} (100%) rename tests/_files/{ignored-lines-crap4j.xml => Report/Crap4j/ignored-lines.xml} (100%) rename tests/_files/{ => Report/OpenClover}/clover.xsd (100%) rename tests/_files/{BankAccount-text-line.txt => Report/Text/BankAccount-line.txt} (100%) rename tests/_files/{BankAccount-text-path.txt => Report/Text/BankAccount-path.txt} (100%) rename tests/_files/{BankAccount-text-summary.txt => Report/Text/BankAccount-summary.txt} (100%) rename tests/_files/{BankAccountWithUncovered-text-line.txt => Report/Text/BankAccountWithUncovered-line.txt} (100%) rename tests/_files/{BankAccountWithoutUncovered-text-line.txt => Report/Text/BankAccountWithoutUncovered-line.txt} (100%) rename tests/_files/{NamespacedBankAccount-text-with-colors.txt => Report/Text/NamespacedBankAccount-colors.txt} (100%) rename tests/_files/{NamespacedBankAccount-text.txt => Report/Text/NamespacedBankAccount.txt} (100%) rename tests/_files/{class-with-anonymous-function-text.txt => Report/Text/class-with-anonymous-function.txt} (100%) rename tests/_files/{ignored-lines-text.txt => Report/Text/ignored-lines.txt} (100%) diff --git a/tests/_files/BankAccount-cobertura-line.xml b/tests/_files/Report/Cobertura/BankAccount-line.xml similarity index 100% rename from tests/_files/BankAccount-cobertura-line.xml rename to tests/_files/Report/Cobertura/BankAccount-line.xml diff --git a/tests/_files/BankAccount-cobertura-path.xml b/tests/_files/Report/Cobertura/BankAccount-path.xml similarity index 100% rename from tests/_files/BankAccount-cobertura-path.xml rename to tests/_files/Report/Cobertura/BankAccount-path.xml diff --git a/tests/_files/class-with-anonymous-function-cobertura.xml b/tests/_files/Report/Cobertura/class-with-anonymous-function.xml similarity index 100% rename from tests/_files/class-with-anonymous-function-cobertura.xml rename to tests/_files/Report/Cobertura/class-with-anonymous-function.xml diff --git a/tests/_files/class-with-outside-function-cobertura.xml b/tests/_files/Report/Cobertura/class-with-outside-function.xml similarity index 100% rename from tests/_files/class-with-outside-function-cobertura.xml rename to tests/_files/Report/Cobertura/class-with-outside-function.xml diff --git a/tests/_files/ignored-lines-cobertura.xml b/tests/_files/Report/Cobertura/ignored-lines.xml similarity index 100% rename from tests/_files/ignored-lines-cobertura.xml rename to tests/_files/Report/Cobertura/ignored-lines.xml diff --git a/tests/_files/BankAccount-crap4j.xml b/tests/_files/Report/Crap4j/BankAccount.xml similarity index 100% rename from tests/_files/BankAccount-crap4j.xml rename to tests/_files/Report/Crap4j/BankAccount.xml diff --git a/tests/_files/class-with-anonymous-function-crap4j.xml b/tests/_files/Report/Crap4j/class-with-anonymous-function.xml similarity index 100% rename from tests/_files/class-with-anonymous-function-crap4j.xml rename to tests/_files/Report/Crap4j/class-with-anonymous-function.xml diff --git a/tests/_files/ignored-lines-crap4j.xml b/tests/_files/Report/Crap4j/ignored-lines.xml similarity index 100% rename from tests/_files/ignored-lines-crap4j.xml rename to tests/_files/Report/Crap4j/ignored-lines.xml diff --git a/tests/_files/clover.xsd b/tests/_files/Report/OpenClover/clover.xsd similarity index 100% rename from tests/_files/clover.xsd rename to tests/_files/Report/OpenClover/clover.xsd diff --git a/tests/_files/BankAccount-text-line.txt b/tests/_files/Report/Text/BankAccount-line.txt similarity index 100% rename from tests/_files/BankAccount-text-line.txt rename to tests/_files/Report/Text/BankAccount-line.txt diff --git a/tests/_files/BankAccount-text-path.txt b/tests/_files/Report/Text/BankAccount-path.txt similarity index 100% rename from tests/_files/BankAccount-text-path.txt rename to tests/_files/Report/Text/BankAccount-path.txt diff --git a/tests/_files/BankAccount-text-summary.txt b/tests/_files/Report/Text/BankAccount-summary.txt similarity index 100% rename from tests/_files/BankAccount-text-summary.txt rename to tests/_files/Report/Text/BankAccount-summary.txt diff --git a/tests/_files/BankAccountWithUncovered-text-line.txt b/tests/_files/Report/Text/BankAccountWithUncovered-line.txt similarity index 100% rename from tests/_files/BankAccountWithUncovered-text-line.txt rename to tests/_files/Report/Text/BankAccountWithUncovered-line.txt diff --git a/tests/_files/BankAccountWithoutUncovered-text-line.txt b/tests/_files/Report/Text/BankAccountWithoutUncovered-line.txt similarity index 100% rename from tests/_files/BankAccountWithoutUncovered-text-line.txt rename to tests/_files/Report/Text/BankAccountWithoutUncovered-line.txt diff --git a/tests/_files/NamespacedBankAccount-text-with-colors.txt b/tests/_files/Report/Text/NamespacedBankAccount-colors.txt similarity index 100% rename from tests/_files/NamespacedBankAccount-text-with-colors.txt rename to tests/_files/Report/Text/NamespacedBankAccount-colors.txt diff --git a/tests/_files/NamespacedBankAccount-text.txt b/tests/_files/Report/Text/NamespacedBankAccount.txt similarity index 100% rename from tests/_files/NamespacedBankAccount-text.txt rename to tests/_files/Report/Text/NamespacedBankAccount.txt diff --git a/tests/_files/class-with-anonymous-function-text.txt b/tests/_files/Report/Text/class-with-anonymous-function.txt similarity index 100% rename from tests/_files/class-with-anonymous-function-text.txt rename to tests/_files/Report/Text/class-with-anonymous-function.txt diff --git a/tests/_files/ignored-lines-text.txt b/tests/_files/Report/Text/ignored-lines.txt similarity index 100% rename from tests/_files/ignored-lines-text.txt rename to tests/_files/Report/Text/ignored-lines.txt diff --git a/tests/tests/Report/CoberturaTest.php b/tests/tests/Report/CoberturaTest.php index 2694bd1e4..48f0667d2 100644 --- a/tests/tests/Report/CoberturaTest.php +++ b/tests/tests/Report/CoberturaTest.php @@ -20,7 +20,7 @@ public function testLineCoverageForBankAccountTest(): void $cobertura = new Cobertura; $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'BankAccount-cobertura-line.xml', + TEST_FILES_PATH . 'Report/Cobertura/BankAccount-line.xml', $cobertura->process($this->getLineCoverageForBankAccount(), null), ); } @@ -30,7 +30,7 @@ public function testPathCoverageForBankAccountTest(): void $cobertura = new Cobertura; $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'BankAccount-cobertura-path.xml', + TEST_FILES_PATH . 'Report/Cobertura/BankAccount-path.xml', $cobertura->process($this->getPathCoverageForBankAccount(), null), ); } @@ -40,7 +40,7 @@ public function testCoberturaForFileWithIgnoredLines(): void $cobertura = new Cobertura; $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'ignored-lines-cobertura.xml', + TEST_FILES_PATH . 'Report/Cobertura/ignored-lines.xml', $cobertura->process($this->getCoverageForFileWithIgnoredLines()), ); } @@ -50,7 +50,7 @@ public function testCoberturaForClassWithAnonymousFunction(): void $cobertura = new Cobertura; $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'class-with-anonymous-function-cobertura.xml', + TEST_FILES_PATH . 'Report/Cobertura/class-with-anonymous-function.xml', $cobertura->process($this->getCoverageForClassWithAnonymousFunction()), ); } @@ -60,7 +60,7 @@ public function testCoberturaForClassAndOutsideFunction(): void $cobertura = new Cobertura; $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'class-with-outside-function-cobertura.xml', + TEST_FILES_PATH . 'Report/Cobertura/class-with-outside-function.xml', $cobertura->process($this->getCoverageForClassWithOutsideFunction()), ); } diff --git a/tests/tests/Report/Crap4jTest.php b/tests/tests/Report/Crap4jTest.php index 72f029027..8e0fb1b06 100644 --- a/tests/tests/Report/Crap4jTest.php +++ b/tests/tests/Report/Crap4jTest.php @@ -20,7 +20,7 @@ public function testForBankAccountTest(): void $crap4j = new Crap4j; $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'BankAccount-crap4j.xml', + TEST_FILES_PATH . 'Report/Crap4j/BankAccount.xml', $crap4j->process($this->getLineCoverageForBankAccount(), null, 'BankAccount'), ); } @@ -30,7 +30,7 @@ public function testForFileWithIgnoredLines(): void $crap4j = new Crap4j; $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'ignored-lines-crap4j.xml', + TEST_FILES_PATH . 'Report/Crap4j/ignored-lines.xml', $crap4j->process($this->getCoverageForFileWithIgnoredLines(), null, 'CoverageForFileWithIgnoredLines'), ); } @@ -40,7 +40,7 @@ public function testForClassWithAnonymousFunction(): void $crap4j = new Crap4j; $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'class-with-anonymous-function-crap4j.xml', + TEST_FILES_PATH . 'Report/Crap4j/class-with-anonymous-function.xml', $crap4j->process($this->getCoverageForClassWithAnonymousFunction(), null, 'CoverageForClassWithAnonymousFunction'), ); } diff --git a/tests/tests/Report/OpenCloverTest.php b/tests/tests/Report/OpenCloverTest.php index 371b47677..0b5a6c659 100644 --- a/tests/tests/Report/OpenCloverTest.php +++ b/tests/tests/Report/OpenCloverTest.php @@ -75,7 +75,7 @@ private function assertAndValidate(string $expectationFile, string $cloverXml): $document = new DOMDocument; $document->loadXML($cloverXml); - if (!$document->schemaValidate(__DIR__ . '/../../_files/clover.xsd')) { + if (!$document->schemaValidate(__DIR__ . '/../../_files/Report/OpenClover/clover.xsd')) { $buffer = 'Generated XML document does not validate against Clover schema:' . PHP_EOL . PHP_EOL; foreach (libxml_get_errors() as $error) { diff --git a/tests/tests/Report/TextTest.php b/tests/tests/Report/TextTest.php index e6e58ffdc..452ee9cab 100644 --- a/tests/tests/Report/TextTest.php +++ b/tests/tests/Report/TextTest.php @@ -24,7 +24,7 @@ public function testLineCoverageForBankAccountTest(): void $text = new Text(Thresholds::default(), false, false); $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'BankAccount-text-line.txt', + TEST_FILES_PATH . 'Report/Text/BankAccount-line.txt', str_replace(PHP_EOL, "\n", $text->process($this->getLineCoverageForBankAccount())), ); } @@ -34,7 +34,7 @@ public function testPathCoverageForBankAccountTest(): void $text = new Text(Thresholds::default(), false, false); $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'BankAccount-text-path.txt', + TEST_FILES_PATH . 'Report/Text/BankAccount-path.txt', str_replace(PHP_EOL, "\n", $text->process($this->getPathCoverageForBankAccount())), ); } @@ -44,7 +44,7 @@ public function testTextOnlySummaryForBankAccountTest(): void $text = new Text(Thresholds::default(), false, true); $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'BankAccount-text-summary.txt', + TEST_FILES_PATH . 'Report/Text/BankAccount-summary.txt', str_replace(PHP_EOL, "\n", $text->process($this->getLineCoverageForBankAccount())), ); } @@ -54,7 +54,7 @@ public function testTextForNamespacedBankAccountTest(): void $text = new Text(Thresholds::default(), true, false); $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'NamespacedBankAccount-text.txt', + TEST_FILES_PATH . 'Report/Text/NamespacedBankAccount.txt', str_replace(PHP_EOL, "\n", $text->process($this->getLineCoverageForNamespacedBankAccount())), ); } @@ -64,7 +64,7 @@ public function testTextForNamespacedBankAccountTestWhenColorsAreEnabled(): void $text = new Text(Thresholds::default(), true, false); $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'NamespacedBankAccount-text-with-colors.txt', + TEST_FILES_PATH . 'Report/Text/NamespacedBankAccount-colors.txt', str_replace(PHP_EOL, "\n", $text->process($this->getLineCoverageForNamespacedBankAccount(), true)), ); } @@ -74,7 +74,7 @@ public function testTextForFileWithIgnoredLines(): void $text = new Text(Thresholds::default(), false, false); $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'ignored-lines-text.txt', + TEST_FILES_PATH . 'Report/Text/ignored-lines.txt', str_replace(PHP_EOL, "\n", $text->process($this->getCoverageForFileWithIgnoredLines())), ); } @@ -84,7 +84,7 @@ public function testTextForClassWithAnonymousFunction(): void $text = new Text(Thresholds::default(), false, false); $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'class-with-anonymous-function-text.txt', + TEST_FILES_PATH . 'Report/Text/class-with-anonymous-function.txt', str_replace(PHP_EOL, "\n", $text->process($this->getCoverageForClassWithAnonymousFunction())), ); } @@ -94,7 +94,7 @@ public function testUncoveredFilesAreIncludedWhenConfiguredTest(): void $text = new Text(Thresholds::default(), false, false); $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'BankAccountWithUncovered-text-line.txt', + TEST_FILES_PATH . 'Report/Text/BankAccountWithUncovered-line.txt', str_replace(PHP_EOL, "\n", $text->process($this->getCoverageForFilesWithUncoveredIncluded())), ); } @@ -104,7 +104,7 @@ public function testUncoveredFilesAreExcludedWhenConfiguredTest(): void $text = new Text(Thresholds::default(), false, false); $this->assertStringMatchesFormatFile( - TEST_FILES_PATH . 'BankAccountWithoutUncovered-text-line.txt', + TEST_FILES_PATH . 'Report/Text/BankAccountWithoutUncovered-line.txt', str_replace(PHP_EOL, "\n", $text->process($this->getCoverageForFilesWithUncoveredExcluded())), ); }