Detailed report for PHPUnit test results

For my recent university php project we had to create a detailed test-report.
First we had the description of our test-cases in the code and also in a seperate overview-table in some wordfile.
Also the output of the PHPUnit test-results was by far not “enterprise ready”, so i started searching for a better solution.

I stumbeld upon a post from Parth Patil, whose solution was to create an xml-report from PHPUnit and then use this xml to create your own report.

I used his solution, made it PHPUnit 3.4 compatible and also added some Reflection to see my testcase doc-comments in the report. (Note: For the refelection i use the Zend_Framework reflection class)

The Result is:
test result

For my TestCase:

class My_Test extends PHPUnit_Framework_TestCase
{
	/**
	 * This is the first demo test, which should succeed
	 * @return void
	 */
	public function testFoo()
	{
		$this->assertTrue(true);
	}
 
	/**
	 * This is the second demo test, which should fail
	 * @return void
	 */
	public function testBar()
	{
		$this->assertTrue(false);
	}
}

And here’s the programming of the report:

class AllTests
{
	public static function main()
	{
		$reportPath = dirname(__FILE__);
 
		// init a PHPUnit test-suite
		$suite = new PHPUnit_Framework_TestSuite('Testsuite Name');
		$suite->addTestSuite('My_Test');
 
		// switch xml output on
		PHPUnit_TextUI_TestRunner::run($suite, array(
			'xmlLogfile' => $reportPath.'/log.xml'
		));
 
		// generate html-report
		self::generateHtmlReport($reportPath);
	}
 
	public static function generateHtmlReport($path)
	{
		$simple = new SimpleXMLElement($path.'/log.xml', null, true);
 
		$output = '';
 
		// loop through each testsuite
		foreach ($simple->xpath('//testsuite') as $testsuite) {
			if (!count($testsuite->testcase)) {
				// has no testcases
				continue;
			}
 
			$output .= '<h1>'.$testsuite['name'].'</h1>';
			$output .= '<table cellspacing="0" class="test_results">
			  <thead>
			    <tr><th>Test Name</th><th>Description</th><th>Result</th><th>Message</th></tr>
			  </thead>
			  <tbody>';
 
			foreach ($testsuite->testcase as $testcase) {
				$reflection = new Zend_Reflection_Method((string)$testcase['class'], (string)$testcase['name']);
				$output .= '<tr><td class="name">'.$testcase['name'].'</td>';
				$output .= '<td class="description">'.nl2br($reflection->getDocblock()->getShortDescription()).'</td>';
 
				if ($testcase->failure) {
					$output .= '<td class="test_fail"/>';
					$output .= '<td><pre>'.htmlspecialchars($testcase->failure).'</td>';
				} else {
					$output .= '<td class="test_pass"/>';
					$output .= '<td>ok</td>';
				}
				$output .= '</tr>';
			}
 
			$output .= '</tbody></table>';
		}
 
		// stylesheet
		$output = '<style> ... see attached zip-file ...</style>'.$output;
 
		// save report
		// file_put_contents($path.'/report.html', $output);
 
		// or output it
		echo $output;
	}
}

Download the php-class for my demo report

In some future i also will add these features:

  • Print which functions each test covers (read the @covers annotation)
  • Show the test-class docBlock-description in the html-report

Related posts:

  1. CSS Counter Test / Auto numbering your google docs headlines with CSS

Tags: , ,

Leave a Reply