1<?php 2/** 3 * @package SimpleTest 4 * @subpackage Extensions 5 * @version $Id$ 6 * @author Patrice Neff - mailinglists@patrice.ch (original code) 7 */ 8 9/** 10 * include SimpleTest reporter 11 */ 12require_once dirname(__FILE__).'/../reporter.php'; 13 14/** 15 * Reporter which outputs test results in a format compatible 16 * with JUnit / Maven XML output. Can be used for integrating 17 * test suite with continuous integration servers such as 18 * Atlassian Bamboo. 19 * @package SimpleTest 20 * @subpackage Extensions 21 */ 22class JUnitXMLReporter extends SimpleReporter { 23 function __construct() { 24 parent::__construct(); 25 $this->doc = new DOMDocument(); 26 $this->doc->loadXML('<testsuite/>'); 27 $this->root = $this->doc->documentElement; 28 } 29 30 function paintHeader($test_name) { 31 $this->testsStart = microtime(true); 32 33 $this->root->setAttribute('name', $test_name); 34 $this->root->setAttribute('timestamp', date('c')); 35 $this->root->setAttribute('hostname', 'localhost'); 36 37 echo "<?xml version=\"1.0\"?>\n"; 38 echo "<!-- starting test suite $test_name\n"; 39 } 40 41 /** 42 * Paints the end of the test with a summary of 43 * the passes and failures. 44 * @param string $test_name Name class of test. 45 * @access public 46 */ 47 function paintFooter($test_name) { 48 echo "-->\n"; 49 echo "\n<testsuites>\n"; 50 51 $duration = microtime(true) - $this->testsStart; 52 53 $this->root->setAttribute('tests', $this->getPassCount() + $this->getFailCount() + $this->getExceptionCount()); 54 $this->root->setAttribute('failures', $this->getFailCount()); 55 $this->root->setAttribute('errors', $this->getExceptionCount()); 56 $this->root->setAttribute('time', $duration); 57 58 $this->doc->formatOutput = true; 59 $xml = $this->doc->saveXML(); 60 // Cut out XML declaration 61 echo preg_replace('/<\?[^>]*\?>/', "", $xml); 62 echo "</testsuites>\n"; 63 } 64 65 function paintCaseStart($case) { 66 echo "- case start $case\n"; 67 $this->currentCaseName = $case; 68 } 69 70 function paintCaseEnd($case) { 71 // No output here 72 } 73 74 function paintMethodStart($test) { 75 echo " - test start: $test\n"; 76 77 $this->methodStart = microtime(true); 78 $this->currCase = $this->doc->createElement('testcase'); 79 } 80 81 function paintMethodEnd($test) { 82 $duration = microtime(true) - $this->methodStart; 83 84 $this->currCase->setAttribute('name', $test); 85 $this->currCase->setAttribute('classname', $this->currentCaseName); 86 $this->currCase->setAttribute('time', $duration); 87 $this->root->appendChild($this->currCase); 88 } 89 90 function paintFail($message) { 91 parent::paintFail($message); 92 93 error_log("Failure: " . $message); 94 $this->terminateAbnormally($message); 95 } 96 97 function paintException($exception) { 98 parent::paintException($exception); 99 100 error_log("Exception: " . $exception); 101 $this->terminateAbnormally($exception); 102 } 103 104 function terminateAbnormally($message) { 105 if (!$this->currCase) { 106 error_log("!! currCase was not set."); 107 return; 108 } 109 110 $ch = $this->doc->createElement('failure'); 111 $breadcrumb = $this->getTestList(); 112 $ch->setAttribute('message', $breadcrumb[count($breadcrumb)-1]); 113 $ch->setAttribute('type', $breadcrumb[count($breadcrumb)-1]); 114 115 $message = implode(' -> ', $breadcrumb) . "\n\n\n" . $message; 116 $content = $this->doc->createTextNode($message); 117 $ch->appendChild($content); 118 119 $this->currCase->appendChild($ch); 120 } 121} 122?>