summaryrefslogtreecommitdiff
path: root/test_tools/simpletest/HtmlReporterWithCoverage.php
diff options
context:
space:
mode:
Diffstat (limited to 'test_tools/simpletest/HtmlReporterWithCoverage.php')
-rw-r--r--test_tools/simpletest/HtmlReporterWithCoverage.php268
1 files changed, 268 insertions, 0 deletions
diff --git a/test_tools/simpletest/HtmlReporterWithCoverage.php b/test_tools/simpletest/HtmlReporterWithCoverage.php
new file mode 100644
index 00000000..abd10076
--- /dev/null
+++ b/test_tools/simpletest/HtmlReporterWithCoverage.php
@@ -0,0 +1,268 @@
+<?php
+
+if (!defined('T_ML_COMMENT'))
+ define('T_ML_COMMENT', T_COMMENT);
+else
+ define('T_DOC_COMMENT', T_ML_COMMENT);
+
+class HtmlReporterWithCoverage extends HtmlReporter
+{
+ protected $coverage = array();
+
+ protected $painter;
+
+ protected $base_dir;
+
+ function __construct($painter = 'index.php', $base_dir)
+ {
+ $this->painter = $painter;
+ $this->base_dir = $base_dir;
+ }
+
+ function paintHeader($test_name, $charset="UTF-8")
+ {
+ $this->sendNoCacheHeaders();
+ header('Content-Type: text/html; Charset='.$charset);
+ print "<html>\n<head>\n<title>$test_name</title>\n";
+ print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset={$charset}\"/>";
+ print "<style type=\"text/css\">\n";
+ print $this->_getCss() . "\n";
+ print "</style>\n";
+ print "</head>\n<body>\n";
+ print "<h1>$test_name</h1>\n";
+ flush();
+
+ if (extension_loaded('xdebug'))
+ xdebug_start_code_coverage(XDEBUG_CC_UNUSED);
+
+ }
+
+ /**
+ *
+ */
+ function _getCss()
+ {
+ $contents = parent::_getCss()."\n ";
+ $contents .= '
+ .bar { float: left; display: inline; border: 1px solid #eee; width: 300px; white-space: nowrap;}
+ .percentage { float: left; background-color: #eef; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 0.65em; padding: 5px; margin-right: }
+ .coverage {margin: 0.4em; }
+ .coverage a {
+ padding-left: 0.5em;
+ }
+ .coverage:after {
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+ }
+ .coverage {display: inline-block;}
+ /* Hides from IE-mac \*/
+ * html .coverage {height: 1%;}
+ .coverage {display: block;}
+ /* End hide from IE-mac */
+ ';
+ Return $contents;
+ }
+
+ function paintFooter($test_name)
+ {
+ if (extension_loaded('xdebug'))
+ {
+ $this->coverage = xdebug_get_code_coverage();
+ xdebug_stop_code_coverage();
+ }
+
+ $colour = ($this->getFailCount() + $this->getExceptionCount() > 0 ? "red" : "green");
+ print "<div style=\"";
+ print "padding: 8px; margin-top: 1em; background-color: $colour; color: white;";
+ print "\">";
+ print $this->getTestCaseProgress() . "/" . $this->getTestCaseCount();
+ print " test cases complete:\n";
+ print "<strong>" . $this->getPassCount() . "</strong> passes, ";
+ print "<strong>" . $this->getFailCount() . "</strong> fails and ";
+ print "<strong>" . $this->getExceptionCount() . "</strong> exceptions.";
+ print "</div>\n";
+ $this->paintCoverage();
+ print "</body>\n</html>\n";
+ }
+
+ function paintCoverage()
+ {
+ $dir = dirname(__FILE__);
+ if(count($this->coverage) > 0)
+ print '<h2>Code Coverage</h2>';
+
+
+ ksort($this->coverage);
+
+ $details = array();
+ foreach($this->coverage as $file => $coverage)
+ {
+ if(is_int(strpos($file, $dir)) == false
+ && is_int(strpos($file, 'simpletest')) == false
+ && is_int(strpos($file, $this->base_dir)))
+ {
+ $total = HTMLCoverageReport::codelines($file);
+ $executed = count($coverage);
+ $percentage = sprintf('%01d',$executed/$total*100);
+ $width = $percentage * 3;
+ $filename = str_replace($this->base_dir, '',$file);
+ $link = $this->constructURL($filename, $coverage);
+
+ $detail['total'] = $total;
+ $detail['executed'] = $executed;
+ $detail['width'] = $width;
+ $detail['filename'] = $filename;
+ $detail['link'] = $link;
+ $details[$percentage][] = $detail;
+ }
+ }
+ krsort($details);
+ foreach($details as $percentage => $files)
+ {
+ foreach($files as $detail)
+ {
+ $total = $detail['total'];
+ $executed = $detail['executed'];
+ $width = $detail['width'];
+ $filename = $detail['filename'];
+ $link = $detail['link'];
+
+ print "<div class=\"coverage\">";
+ print "<span class=\"bar\">";
+ print "<span class=\"percentage\" style=\"width:{$width}px\">";
+ print "$executed/$total\n";
+ print "$percentage%</span></span>\n";
+ print "<a href=\"{$link}\">{$filename}</a>\n";
+ print "</div>\n";
+ }
+ }
+ }
+
+ function constructURL($file, $coverage)
+ {
+ $file = rawurlencode($file);
+ $lines = implode(',', array_keys($coverage));
+ return $this->painter.'?file='.$file.'&amp;lines='.$lines;
+ }
+}
+
+
+class HTMLCoverageReport extends HtmlReporter
+{
+ protected $file;
+ protected $lines;
+ protected $name;
+
+ function __construct($file, $name, $lines)
+ {
+ $this->file = $file;
+ $this->lines = $lines;
+ $this->name = $name;
+ }
+
+ function show()
+ {
+ $this->paintHeader($this->name);
+
+ $contents = file($this->file);
+ foreach($contents as $count => $line)
+ {
+ $num = ($count+1);
+ $line = preg_replace("/\\n|\\r/",'',$line);
+ $line = htmlspecialchars($line);
+ $line = str_replace(' ','&nbsp;',$line);
+ $line = str_replace("\t",'&nbsp;&nbsp;&nbsp;&nbsp;',$line);
+ if(in_array($count+1, $this->lines))
+ echo "<div class=\"highlight\"><tt>$num $line</tt></div>\n";
+ else
+ echo "<tt>$num $line</tt><br />\n";
+ }
+
+ $this->paintFooter();
+ }
+
+ function paintHeader($file, $charset="UTF-8")
+ {
+ $total = $this->codelines($this->file);
+ $executed = count($this->lines);
+ $percentage = sprintf('%01.2f',$executed/$total*100);
+
+ $this->sendNoCacheHeaders();
+ header('Content-Type: text/html Charset='.$charset);
+ print "<html>\n<head>\n<title>Code Coverage: $file</title>\n";
+ print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset={$charset}\"/>";
+ print "<style type=\"text/css\">\n";
+ print $this->_getCss() . "\n";
+ print ".highlight { background-color: #eef; } \n";
+ print ".filename { margin-bottom: 2em; } \n";
+ print "</style>\n";
+ print "</head>\n<body>\n";
+ print "<h1>Code Coverage</h1>\n";
+ print "<div class=\"filename\"><strong>$file</strong></div>";
+ print "<div class=\"filename\"><tt>&nbsp;&nbsp;&nbsp;&nbsp;Total code lines: {$total} <br /> Total lines executed: {$executed} ({$percentage}%)</tt></div>";
+ flush();
+ }
+
+ function paintFooter($test_name)
+ {
+ print "</body>\n</html>\n";
+ }
+
+ static function codelines($file)
+ {
+ $source = file_get_contents($file);
+ $tokens = @token_get_all($source);
+
+ $lines = '';
+
+ foreach ($tokens as $token)
+ {
+ if (is_string($token))
+ {
+ // simple 1-character token
+ $lines .= $token;
+ }
+ else
+ {
+ // token array
+ list($id, $text) = $token;
+
+ switch ($id)
+ {
+ case T_COMMENT:
+ case T_ML_COMMENT: // we've defined this
+ case T_DOC_COMMENT: // and this
+ // no action on comments
+ break;
+
+ default:
+ // anything else -> output "as is"
+ //echo $text;
+ $lines .= $text;
+ break;
+ }
+ }
+ }
+
+ $lines = preg_replace('/\\n\s*$/m',"",$lines);
+ $codelines = explode("\n",$lines);
+ $count = 0;
+ $patterns[] = '^\s*{\s*$';
+ $patterns[] = '<\?';
+ $patterns[] = '^\s*(private|protected|public)\s+\$';
+ $pattern = '/'.implode('|', $patterns).'/';
+ foreach($codelines as $line)
+ {
+ if(!preg_match($pattern, $line))
+ $count++;
+ }
+ return $count;
+ //var_dump($codelines);
+ //return count($codelines);
+ }
+}
+
+?>