1<?php 2/* 3 * This file is part of PHPUnit. 4 * 5 * (c) Sebastian Bergmann <sebastian@phpunit.de> 6 * 7 * For the full copyright and license information, please view the LICENSE 8 * file that was distributed with this source code. 9 */ 10 11class PHPUnit_Util_TestDox_ResultPrinter_XML extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener 12{ 13 /** 14 * @var DOMDocument 15 */ 16 private $document; 17 18 /** 19 * @var DOMElement 20 */ 21 private $root; 22 23 /** 24 * @var PHPUnit_Util_TestDox_NamePrettifier 25 */ 26 private $prettifier; 27 28 /** 29 * @var Exception 30 */ 31 private $exception; 32 33 /** 34 * @param string|resource $out 35 */ 36 public function __construct($out = null) 37 { 38 $this->document = new DOMDocument('1.0', 'UTF-8'); 39 $this->document->formatOutput = true; 40 41 $this->root = $this->document->createElement('tests'); 42 $this->document->appendChild($this->root); 43 44 $this->prettifier = new PHPUnit_Util_TestDox_NamePrettifier; 45 46 parent::__construct($out); 47 } 48 49 /** 50 * Flush buffer and close output. 51 */ 52 public function flush() 53 { 54 $this->write($this->document->saveXML()); 55 56 parent::flush(); 57 } 58 59 /** 60 * An error occurred. 61 * 62 * @param PHPUnit_Framework_Test $test 63 * @param Exception $e 64 * @param float $time 65 */ 66 public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) 67 { 68 $this->exception = $e; 69 } 70 71 /** 72 * A warning occurred. 73 * 74 * @param PHPUnit_Framework_Test $test 75 * @param PHPUnit_Framework_Warning $e 76 * @param float $time 77 */ 78 public function addWarning(PHPUnit_Framework_Test $test, PHPUnit_Framework_Warning $e, $time) 79 { 80 } 81 82 /** 83 * A failure occurred. 84 * 85 * @param PHPUnit_Framework_Test $test 86 * @param PHPUnit_Framework_AssertionFailedError $e 87 * @param float $time 88 */ 89 public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) 90 { 91 $this->exception = $e; 92 } 93 94 /** 95 * Incomplete test. 96 * 97 * @param PHPUnit_Framework_Test $test 98 * @param Exception $e 99 * @param float $time 100 */ 101 public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) 102 { 103 } 104 105 /** 106 * Risky test. 107 * 108 * @param PHPUnit_Framework_Test $test 109 * @param Exception $e 110 * @param float $time 111 */ 112 public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) 113 { 114 } 115 116 /** 117 * Skipped test. 118 * 119 * @param PHPUnit_Framework_Test $test 120 * @param Exception $e 121 * @param float $time 122 */ 123 public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) 124 { 125 } 126 127 /** 128 * A test suite started. 129 * 130 * @param PHPUnit_Framework_TestSuite $suite 131 */ 132 public function startTestSuite(PHPUnit_Framework_TestSuite $suite) 133 { 134 } 135 136 /** 137 * A test suite ended. 138 * 139 * @param PHPUnit_Framework_TestSuite $suite 140 */ 141 public function endTestSuite(PHPUnit_Framework_TestSuite $suite) 142 { 143 } 144 145 /** 146 * A test started. 147 * 148 * @param PHPUnit_Framework_Test $test 149 */ 150 public function startTest(PHPUnit_Framework_Test $test) 151 { 152 $this->exception = null; 153 } 154 155 /** 156 * A test ended. 157 * 158 * @param PHPUnit_Framework_Test $test 159 * @param float $time 160 */ 161 public function endTest(PHPUnit_Framework_Test $test, $time) 162 { 163 if (!$test instanceof PHPUnit_Framework_TestCase) { 164 return; 165 } 166 167 /* @var PHPUnit_Framework_TestCase $test */ 168 169 $groups = array_filter( 170 $test->getGroups(), 171 function ($group) { 172 if ($group == 'small' || $group == 'medium' || $group == 'large') { 173 return false; 174 } 175 176 return true; 177 } 178 ); 179 180 $node = $this->document->createElement('test'); 181 182 $node->setAttribute('className', get_class($test)); 183 $node->setAttribute('methodName', $test->getName()); 184 $node->setAttribute('prettifiedClassName', $this->prettifier->prettifyTestClass(get_class($test))); 185 $node->setAttribute('prettifiedMethodName', $this->prettifier->prettifyTestMethod($test->getName())); 186 $node->setAttribute('status', $test->getStatus()); 187 $node->setAttribute('time', $time); 188 $node->setAttribute('size', $test->getSize()); 189 $node->setAttribute('groups', implode(',', $groups)); 190 191 $inlineAnnotations = PHPUnit_Util_Test::getInlineAnnotations(get_class($test), $test->getName()); 192 193 if (isset($inlineAnnotations['given']) && isset($inlineAnnotations['when']) && isset($inlineAnnotations['then'])) { 194 $node->setAttribute('given', $inlineAnnotations['given']['value']); 195 $node->setAttribute('givenStartLine', $inlineAnnotations['given']['line']); 196 $node->setAttribute('when', $inlineAnnotations['when']['value']); 197 $node->setAttribute('whenStartLine', $inlineAnnotations['when']['line']); 198 $node->setAttribute('then', $inlineAnnotations['then']['value']); 199 $node->setAttribute('thenStartLine', $inlineAnnotations['then']['line']); 200 } 201 202 if ($this->exception !== null) { 203 if ($this->exception instanceof PHPUnit_Framework_Exception) { 204 $steps = $this->exception->getSerializableTrace(); 205 } else { 206 $steps = $this->exception->getTrace(); 207 } 208 209 $class = new ReflectionClass($test); 210 $file = $class->getFileName(); 211 212 foreach ($steps as $step) { 213 if (isset($step['file']) && $step['file'] == $file) { 214 $node->setAttribute('exceptionLine', $step['line']); 215 216 break; 217 } 218 } 219 220 $node->setAttribute('exceptionMessage', $this->exception->getMessage()); 221 } 222 223 $this->root->appendChild($node); 224 } 225} 226