Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php declare(strict_types=1);/** This file is part of PHPUnit.** (c) Sebastian Bergmann <sebastian@phpunit.de>** For the full copyright and license information, please view the LICENSE* file that was distributed with this source code.*/namespace PHPUnit\Util\TestDox;use function array_filter;use function get_class;use function implode;use function strpos;use DOMDocument;use DOMElement;use PHPUnit\Framework\AssertionFailedError;use PHPUnit\Framework\Exception;use PHPUnit\Framework\Test;use PHPUnit\Framework\TestCase;use PHPUnit\Framework\TestListener;use PHPUnit\Framework\TestSuite;use PHPUnit\Framework\Warning;use PHPUnit\Framework\WarningTestCase;use PHPUnit\Util\Printer;use PHPUnit\Util\Test as TestUtil;use ReflectionClass;use ReflectionException;use Throwable;/*** @internal This class is not covered by the backward compatibility promise for PHPUnit*/final class XmlResultPrinter extends Printer implements TestListener{/*** @var DOMDocument*/private $document;/*** @var DOMElement*/private $root;/*** @var NamePrettifier*/private $prettifier;/*** @var null|Throwable*/private $exception;/*** @param resource|string $out** @throws Exception*/public function __construct($out = null){$this->document = new DOMDocument('1.0', 'UTF-8');$this->document->formatOutput = true;$this->root = $this->document->createElement('tests');$this->document->appendChild($this->root);$this->prettifier = new NamePrettifier;parent::__construct($out);}/*** Flush buffer and close output.*/public function flush(): void{$this->write($this->document->saveXML());parent::flush();}/*** An error occurred.*/public function addError(Test $test, Throwable $t, float $time): void{$this->exception = $t;}/*** A warning occurred.*/public function addWarning(Test $test, Warning $e, float $time): void{}/*** A failure occurred.*/public function addFailure(Test $test, AssertionFailedError $e, float $time): void{$this->exception = $e;}/*** Incomplete test.*/public function addIncompleteTest(Test $test, Throwable $t, float $time): void{}/*** Risky test.*/public function addRiskyTest(Test $test, Throwable $t, float $time): void{}/*** Skipped test.*/public function addSkippedTest(Test $test, Throwable $t, float $time): void{}/*** A test suite started.*/public function startTestSuite(TestSuite $suite): void{}/*** A test suite ended.*/public function endTestSuite(TestSuite $suite): void{}/*** A test started.*/public function startTest(Test $test): void{$this->exception = null;}/*** A test ended.** @throws \SebastianBergmann\RecursionContext\InvalidArgumentException*/public function endTest(Test $test, float $time): void{if (!$test instanceof TestCase || $test instanceof WarningTestCase) {return;}$groups = array_filter($test->getGroups(),static function ($group){return !($group === 'small' || $group === 'medium' || $group === 'large' || strpos($group, '__phpunit_') === 0);});$testNode = $this->document->createElement('test');$testNode->setAttribute('className', get_class($test));$testNode->setAttribute('methodName', $test->getName());$testNode->setAttribute('prettifiedClassName', $this->prettifier->prettifyTestClass(get_class($test)));$testNode->setAttribute('prettifiedMethodName', $this->prettifier->prettifyTestCase($test));$testNode->setAttribute('status', (string) $test->getStatus());$testNode->setAttribute('time', (string) $time);$testNode->setAttribute('size', (string) $test->getSize());$testNode->setAttribute('groups', implode(',', $groups));foreach ($groups as $group) {$groupNode = $this->document->createElement('group');$groupNode->setAttribute('name', $group);$testNode->appendChild($groupNode);}$annotations = TestUtil::parseTestMethodAnnotations(get_class($test),$test->getName(false));foreach (['class', 'method'] as $type) {foreach ($annotations[$type] as $annotation => $values) {if ($annotation !== 'covers' && $annotation !== 'uses') {continue;}foreach ($values as $value) {$coversNode = $this->document->createElement($annotation);$coversNode->setAttribute('target', $value);$testNode->appendChild($coversNode);}}}foreach ($test->doubledTypes() as $doubledType) {$testDoubleNode = $this->document->createElement('testDouble');$testDoubleNode->setAttribute('type', $doubledType);$testNode->appendChild($testDoubleNode);}$inlineAnnotations = \PHPUnit\Util\Test::getInlineAnnotations(get_class($test), $test->getName(false));if (isset($inlineAnnotations['given'], $inlineAnnotations['when'], $inlineAnnotations['then'])) {$testNode->setAttribute('given', $inlineAnnotations['given']['value']);$testNode->setAttribute('givenStartLine', (string) $inlineAnnotations['given']['line']);$testNode->setAttribute('when', $inlineAnnotations['when']['value']);$testNode->setAttribute('whenStartLine', (string) $inlineAnnotations['when']['line']);$testNode->setAttribute('then', $inlineAnnotations['then']['value']);$testNode->setAttribute('thenStartLine', (string) $inlineAnnotations['then']['line']);}if ($this->exception !== null) {if ($this->exception instanceof Exception) {$steps = $this->exception->getSerializableTrace();} else {$steps = $this->exception->getTrace();}try {$file = (new ReflectionClass($test))->getFileName();// @codeCoverageIgnoreStart} catch (ReflectionException $e) {throw new Exception($e->getMessage(),$e->getCode(),$e);}// @codeCoverageIgnoreEndforeach ($steps as $step) {if (isset($step['file']) && $step['file'] === $file) {$testNode->setAttribute('exceptionLine', (string) $step['line']);break;}}$testNode->setAttribute('exceptionMessage', $this->exception->getMessage());}$this->root->appendChild($testNode);}}