Skip to content

Add branch coverage stats to xml report #1057

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/Report/Xml/Facade.php
Original file line number Diff line number Diff line change
@@ -252,6 +252,16 @@ private function setTotals(AbstractNode $node, Totals $totals): void
$node->numberOfExecutedLines(),
);

$totals->setNumBranches(
$node->numberOfExecutableBranches(),
$node->numberOfExecutedBranches(),
);

$totals->setNumPaths(
$node->numberOfExecutablePaths(),
$node->numberOfExecutedPaths(),
);

$totals->setNumClasses(
$node->numberOfClasses(),
$node->numberOfTestedClasses(),
34 changes: 34 additions & 0 deletions src/Report/Xml/Totals.php
Original file line number Diff line number Diff line change
@@ -21,6 +21,8 @@
{
private DOMNode $container;
private DOMElement $linesNode;
private DOMElement $branchesNode;
private DOMElement $pathsNode;
private DOMElement $methodsNode;
private DOMElement $functionsNode;
private DOMElement $classesNode;
@@ -36,6 +38,16 @@ public function __construct(DOMElement $container)
'lines',
);

$this->branchesNode = $dom->createElementNS(
'https://schema.phpunit.de/coverage/1.0',
'branches',
);

$this->pathsNode = $dom->createElementNS(
'https://schema.phpunit.de/coverage/1.0',
'paths',
);

$this->methodsNode = $dom->createElementNS(
'https://schema.phpunit.de/coverage/1.0',
'methods',
@@ -57,6 +69,8 @@ public function __construct(DOMElement $container)
);

$container->appendChild($this->linesNode);
$container->appendChild($this->branchesNode);
$container->appendChild($this->pathsNode);
$container->appendChild($this->methodsNode);
$container->appendChild($this->functionsNode);
$container->appendChild($this->classesNode);
@@ -81,6 +95,26 @@ public function setNumLines(int $loc, int $cloc, int $ncloc, int $executable, in
);
}

public function setNumBranches(int $count, int $tested): void
{
$this->branchesNode->setAttribute('count', (string) $count);
$this->branchesNode->setAttribute('tested', (string) $tested);
$this->branchesNode->setAttribute(
'percent',
$count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()),
);
}

public function setNumPaths(int $count, int $tested): void
{
$this->pathsNode->setAttribute('count', (string) $count);
$this->pathsNode->setAttribute('tested', (string) $tested);
$this->pathsNode->setAttribute(
'percent',
$count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()),
);
}

public function setNumClasses(int $count, int $tested): void
{
$this->classesNode->setAttribute('count', (string) $count);
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
<file name="BankAccount.php" path="%e">
<totals>
<lines total="35" comments="0" code="35" executable="8" executed="5" percent="62.50"/>
<branches count="0" tested="0" percent="0"/>
<paths count="0" tested="0" percent="0"/>
<methods count="4" tested="3" percent="75.00"/>
<functions count="0" tested="0" percent="0"/>
<classes count="1" tested="0" percent="0.00"/>
4 changes: 4 additions & 0 deletions tests/_files/Report/XML/CoverageForBankAccount/index.xml
Original file line number Diff line number Diff line change
@@ -14,6 +14,8 @@
<directory name="%s">
<totals>
<lines total="35" comments="0" code="35" executable="8" executed="5" percent="62.50"/>
<branches count="0" tested="0" percent="0"/>
<paths count="0" tested="0" percent="0"/>
<methods count="4" tested="3" percent="75.00"/>
<functions count="0" tested="0" percent="0"/>
<classes count="1" tested="0" percent="0.00"/>
@@ -22,6 +24,8 @@
<file name="BankAccount.php" href="BankAccount.php.xml">
<totals>
<lines total="35" comments="0" code="35" executable="8" executed="5" percent="62.50"/>
<branches count="0" tested="0" percent="0"/>
<paths count="0" tested="0" percent="0"/>
<methods count="4" tested="3" percent="75.00"/>
<functions count="0" tested="0" percent="0"/>
<classes count="1" tested="0" percent="0.00"/>
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@
<directory name="%s">
<totals>
<lines total="20" comments="1" code="19" executable="8" executed="8" percent="100.00"/>
<branches count="0" tested="0" percent="0"/>
<paths count="0" tested="0" percent="0"/>
<methods count="1" tested="1" percent="100.00"/>
<functions count="0" tested="0" percent="0"/>
<classes count="1" tested="1" percent="100.00"/>
@@ -19,6 +21,8 @@
<file name="source_with_class_and_anonymous_function.php" href="source_with_class_and_anonymous_function.php.xml">
<totals>
<lines total="20" comments="1" code="19" executable="8" executed="8" percent="100.00"/>
<branches count="0" tested="0" percent="0"/>
<paths count="0" tested="0" percent="0"/>
<methods count="1" tested="1" percent="100.00"/>
<functions count="0" tested="0" percent="0"/>
<classes count="1" tested="1" percent="100.00"/>
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
<file name="source_with_class_and_anonymous_function.php" path="%e">
<totals>
<lines total="20" comments="1" code="19" executable="8" executed="8" percent="100.00"/>
<branches count="0" tested="0" percent="0"/>
<paths count="0" tested="0" percent="0"/>
<methods count="1" tested="1" percent="100.00"/>
<functions count="0" tested="0" percent="0"/>
<classes count="1" tested="1" percent="100.00"/>
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@
<directory name="%s">
<totals>
<lines total="43" comments="11" code="32" executable="1" executed="1" percent="100.00"/>
<branches count="0" tested="0" percent="0"/>
<paths count="0" tested="0" percent="0"/>
<methods count="0" tested="0" percent="0"/>
<functions count="1" tested="1" percent="100.00"/>
<classes count="0" tested="0" percent="0"/>
@@ -19,6 +21,8 @@
<file name="source_with_ignore.php" href="source_with_ignore.php.xml">
<totals>
<lines total="43" comments="11" code="32" executable="1" executed="1" percent="100.00"/>
<branches count="0" tested="0" percent="0"/>
<paths count="0" tested="0" percent="0"/>
<methods count="0" tested="0" percent="0"/>
<functions count="1" tested="1" percent="100.00"/>
<classes count="0" tested="0" percent="0"/>
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
<file name="source_with_ignore.php" path="%e">
<totals>
<lines total="43" comments="11" code="32" executable="1" executed="1" percent="100.00"/>
<branches count="0" tested="0" percent="0"/>
<paths count="0" tested="0" percent="0"/>
<methods count="0" tested="0" percent="0"/>
<functions count="1" tested="1" percent="100.00"/>
<classes count="0" tested="0" percent="0"/>
274 changes: 274 additions & 0 deletions tests/_files/Report/XML/PathCoverageForBankAccount/BankAccount.php.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
<?xml version="1.0"?>
<phpunit xmlns="https://schema.phpunit.de/coverage/1.0">
<file name="BankAccount.php" path="%e">
<totals>
<lines total="35" comments="0" code="35" executable="8" executed="5" percent="62.50"/>
<branches count="7" tested="3" percent="42.86"/>
<paths count="5" tested="3" percent="60.00"/>
<methods count="4" tested="3" percent="75.00"/>
<functions count="0" tested="0" percent="0"/>
<classes count="1" tested="0" percent="0.00"/>
<traits count="0" tested="0" percent="0"/>
</totals>
<class name="BankAccount" start="2" executable="8" executed="5" crap="6.6">
<namespace name=""/>
<method name="getBalance" signature="getBalance()" start="6" end="9" crap="1" executable="1" executed="1" coverage="100"/>
<method name="setBalance" signature="setBalance($balance)" start="11" end="18" crap="6" executable="3" executed="0" coverage="0"/>
<method name="depositMoney" signature="depositMoney($balance)" start="20" end="25" crap="1" executable="2" executed="2" coverage="100"/>
<method name="withdrawMoney" signature="withdrawMoney($balance)" start="27" end="33" crap="1" executable="2" executed="2" coverage="100"/>
</class>
<coverage>
<line nr="8">
<covered by="BankAccountTest::testBalanceIsInitiallyZero"/>
<covered by="BankAccountTest::testDepositWithdrawMoney"/>
</line>
<line nr="22">
<covered by="BankAccountTest::testBalanceCannotBecomeNegative2"/>
<covered by="BankAccountTest::testDepositWithdrawMoney"/>
</line>
<line nr="24">
<covered by="BankAccountTest::testDepositWithdrawMoney"/>
</line>
<line nr="29">
<covered by="BankAccountTest::testBalanceCannotBecomeNegative"/>
<covered by="BankAccountTest::testDepositWithdrawMoney"/>
</line>
<line nr="31">
<covered by="BankAccountTest::testDepositWithdrawMoney"/>
</line>
</coverage>
<source>
<line no="1">
<token name="T_OPEN_TAG">&lt;?php</token>
</line>
<line no="2">
<token name="T_CLASS">class</token>
<token name="T_WHITESPACE"> </token>
<token name="T_STRING">BankAccount</token>
</line>
<line no="3">
<token name="T_OPEN_CURLY">{</token>
</line>
<line no="4">
<token name="T_WHITESPACE"> </token>
<token name="T_PROTECTED">protected</token>
<token name="T_WHITESPACE"> </token>
<token name="T_VARIABLE">$balance</token>
<token name="T_WHITESPACE"> </token>
<token name="T_EQUAL">=</token>
<token name="T_WHITESPACE"> </token>
<token name="T_LNUMBER">0</token>
<token name="T_SEMICOLON">;</token>
</line>
<line no="5"/>
<line no="6">
<token name="T_WHITESPACE"> </token>
<token name="T_PUBLIC">public</token>
<token name="T_WHITESPACE"> </token>
<token name="T_FUNCTION">function</token>
<token name="T_WHITESPACE"> </token>
<token name="T_STRING">getBalance</token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_CLOSE_BRACKET">)</token>
</line>
<line no="7">
<token name="T_WHITESPACE"> </token>
<token name="T_OPEN_CURLY">{</token>
</line>
<line no="8">
<token name="T_WHITESPACE"> </token>
<token name="T_RETURN">return</token>
<token name="T_WHITESPACE"> </token>
<token name="T_VARIABLE">$this</token>
<token name="T_OBJECT_OPERATOR">-&gt;</token>
<token name="T_STRING">balance</token>
<token name="T_SEMICOLON">;</token>
</line>
<line no="9">
<token name="T_WHITESPACE"> </token>
<token name="T_CLOSE_CURLY">}</token>
</line>
<line no="10"/>
<line no="11">
<token name="T_WHITESPACE"> </token>
<token name="T_PROTECTED">protected</token>
<token name="T_WHITESPACE"> </token>
<token name="T_FUNCTION">function</token>
<token name="T_WHITESPACE"> </token>
<token name="T_STRING">setBalance</token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_VARIABLE">$balance</token>
<token name="T_CLOSE_BRACKET">)</token>
</line>
<line no="12">
<token name="T_WHITESPACE"> </token>
<token name="T_OPEN_CURLY">{</token>
</line>
<line no="13">
<token name="T_WHITESPACE"> </token>
<token name="T_IF">if</token>
<token name="T_WHITESPACE"> </token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_VARIABLE">$balance</token>
<token name="T_WHITESPACE"> </token>
<token name="T_IS_GREATER_OR_EQUAL">&gt;=</token>
<token name="T_WHITESPACE"> </token>
<token name="T_LNUMBER">0</token>
<token name="T_CLOSE_BRACKET">)</token>
<token name="T_WHITESPACE"> </token>
<token name="T_OPEN_CURLY">{</token>
</line>
<line no="14">
<token name="T_WHITESPACE"> </token>
<token name="T_VARIABLE">$this</token>
<token name="T_OBJECT_OPERATOR">-&gt;</token>
<token name="T_STRING">balance</token>
<token name="T_WHITESPACE"> </token>
<token name="T_EQUAL">=</token>
<token name="T_WHITESPACE"> </token>
<token name="T_VARIABLE">$balance</token>
<token name="T_SEMICOLON">;</token>
</line>
<line no="15">
<token name="T_WHITESPACE"> </token>
<token name="T_CLOSE_CURLY">}</token>
<token name="T_WHITESPACE"> </token>
<token name="T_ELSE">else</token>
<token name="T_WHITESPACE"> </token>
<token name="T_OPEN_CURLY">{</token>
</line>
<line no="16">
<token name="T_WHITESPACE"> </token>
<token name="T_THROW">throw</token>
<token name="T_WHITESPACE"> </token>
<token name="T_NEW">new</token>
<token name="T_WHITESPACE"> </token>
<token name="T_STRING">RuntimeException</token>
<token name="T_SEMICOLON">;</token>
</line>
<line no="17">
<token name="T_WHITESPACE"> </token>
<token name="T_CLOSE_CURLY">}</token>
</line>
<line no="18">
<token name="T_WHITESPACE"> </token>
<token name="T_CLOSE_CURLY">}</token>
</line>
<line no="19"/>
<line no="20">
<token name="T_WHITESPACE"> </token>
<token name="T_PUBLIC">public</token>
<token name="T_WHITESPACE"> </token>
<token name="T_FUNCTION">function</token>
<token name="T_WHITESPACE"> </token>
<token name="T_STRING">depositMoney</token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_VARIABLE">$balance</token>
<token name="T_CLOSE_BRACKET">)</token>
</line>
<line no="21">
<token name="T_WHITESPACE"> </token>
<token name="T_OPEN_CURLY">{</token>
</line>
<line no="22">
<token name="T_WHITESPACE"> </token>
<token name="T_VARIABLE">$this</token>
<token name="T_OBJECT_OPERATOR">-&gt;</token>
<token name="T_STRING">setBalance</token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_VARIABLE">$this</token>
<token name="T_OBJECT_OPERATOR">-&gt;</token>
<token name="T_STRING">getBalance</token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_CLOSE_BRACKET">)</token>
<token name="T_WHITESPACE"> </token>
<token name="T_PLUS">+</token>
<token name="T_WHITESPACE"> </token>
<token name="T_VARIABLE">$balance</token>
<token name="T_CLOSE_BRACKET">)</token>
<token name="T_SEMICOLON">;</token>
</line>
<line no="23"/>
<line no="24">
<token name="T_WHITESPACE"> </token>
<token name="T_RETURN">return</token>
<token name="T_WHITESPACE"> </token>
<token name="T_VARIABLE">$this</token>
<token name="T_OBJECT_OPERATOR">-&gt;</token>
<token name="T_STRING">getBalance</token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_CLOSE_BRACKET">)</token>
<token name="T_SEMICOLON">;</token>
</line>
<line no="25">
<token name="T_WHITESPACE"> </token>
<token name="T_CLOSE_CURLY">}</token>
</line>
<line no="26"/>
<line no="27">
<token name="T_WHITESPACE"> </token>
<token name="T_PUBLIC">public</token>
<token name="T_WHITESPACE"> </token>
<token name="T_FUNCTION">function</token>
<token name="T_WHITESPACE"> </token>
<token name="T_STRING">withdrawMoney</token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_VARIABLE">$balance</token>
<token name="T_CLOSE_BRACKET">)</token>
</line>
<line no="28">
<token name="T_WHITESPACE"> </token>
<token name="T_OPEN_CURLY">{</token>
</line>
<line no="29">
<token name="T_WHITESPACE"> </token>
<token name="T_VARIABLE">$this</token>
<token name="T_OBJECT_OPERATOR">-&gt;</token>
<token name="T_STRING">setBalance</token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_VARIABLE">$this</token>
<token name="T_OBJECT_OPERATOR">-&gt;</token>
<token name="T_STRING">getBalance</token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_CLOSE_BRACKET">)</token>
<token name="T_WHITESPACE"> </token>
<token name="T_MINUS">-</token>
<token name="T_WHITESPACE"> </token>
<token name="T_VARIABLE">$balance</token>
<token name="T_CLOSE_BRACKET">)</token>
<token name="T_SEMICOLON">;</token>
</line>
<line no="30"/>
<line no="31">
<token name="T_WHITESPACE"> </token>
<token name="T_RETURN">return</token>
<token name="T_WHITESPACE"> </token>
<token name="T_VARIABLE">$this</token>
<token name="T_OBJECT_OPERATOR">-&gt;</token>
<token name="T_STRING">getBalance</token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_CLOSE_BRACKET">)</token>
<token name="T_SEMICOLON">;</token>
</line>
<line no="32">
<token name="T_WHITESPACE"> </token>
<token name="T_RETURN">return</token>
<token name="T_WHITESPACE"> </token>
<token name="T_VARIABLE">$this</token>
<token name="T_OBJECT_OPERATOR">-&gt;</token>
<token name="T_STRING">getBalance</token>
<token name="T_OPEN_BRACKET">(</token>
<token name="T_CLOSE_BRACKET">)</token>
<token name="T_SEMICOLON">;</token>
</line>
<line no="33">
<token name="T_WHITESPACE"> </token>
<token name="T_CLOSE_CURLY">}</token>
</line>
<line no="34">
<token name="T_CLOSE_CURLY">}</token>
</line>
<line no="35"/>
</source>
</file>
</phpunit>
37 changes: 37 additions & 0 deletions tests/_files/Report/XML/PathCoverageForBankAccount/index.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0"?>
<phpunit xmlns="https://schema.phpunit.de/coverage/1.0">
<build time="%s" phpunit="%s" coverage="%s">
<runtime name="%s" version="%s" url="%s"/>
<driver%S/>
</build>
<project source="%s">
<tests>
<test name="BankAccountTest::testBalanceIsInitiallyZero" size="unknown" status="unknown"/>
<test name="BankAccountTest::testBalanceCannotBecomeNegative" size="unknown" status="unknown"/>
<test name="BankAccountTest::testBalanceCannotBecomeNegative2" size="unknown" status="unknown"/>
<test name="BankAccountTest::testDepositWithdrawMoney" size="unknown" status="unknown"/>
</tests>
<directory name="%s">
<totals>
<lines total="35" comments="0" code="35" executable="8" executed="5" percent="62.50"/>
<branches count="7" tested="3" percent="42.86"/>
<paths count="5" tested="3" percent="60.00"/>
<methods count="4" tested="3" percent="75.00"/>
<functions count="0" tested="0" percent="0"/>
<classes count="1" tested="0" percent="0.00"/>
<traits count="0" tested="0" percent="0"/>
</totals>
<file name="BankAccount.php" href="BankAccount.php.xml">
<totals>
<lines total="35" comments="0" code="35" executable="8" executed="5" percent="62.50"/>
<branches count="7" tested="3" percent="42.86"/>
<paths count="5" tested="3" percent="60.00"/>
<methods count="4" tested="3" percent="75.00"/>
<functions count="0" tested="0" percent="0"/>
<classes count="1" tested="0" percent="0.00"/>
<traits count="0" tested="0" percent="0"/>
</totals>
</file>
</directory>
</project>
</phpunit>
10 changes: 10 additions & 0 deletions tests/tests/Report/XmlTest.php
Original file line number Diff line number Diff line change
@@ -67,6 +67,16 @@ public function testForClassWithAnonymousFunction(): void
$this->assertFilesEquals($expectedFilesPath, TEST_FILES_PATH . 'tmp');
}

public function testForBankAccountWithPathCoverage(): void
{
$expectedFilesPath = self::$TEST_REPORT_PATH_SOURCE . DIRECTORY_SEPARATOR . 'PathCoverageForBankAccount';

$xml = new Facade('1.0.0');
$xml->process($this->getPathCoverageForBankAccount(), TEST_FILES_PATH . 'tmp');

$this->assertFilesEquals($expectedFilesPath, TEST_FILES_PATH . 'tmp');
}

private function assertFilesEquals(string $expectedFilesPath, string $actualFilesPath): void
{
$expectedFilesIterator = new FilesystemIterator($expectedFilesPath);