Skip to content

Commit a7b0b81

Browse files
committed
Merge branch 'master' into omni
Conflicts: bootstrap.php units/test_posts.php
2 parents e58bbc0 + 2c168b5 commit a7b0b81

File tree

6 files changed

+930
-344
lines changed

6 files changed

+930
-344
lines changed

bootstrap.php

Lines changed: 117 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,19 @@
1717
* -o : Display output.
1818
* -i : Display method timers.
1919
* -u {unitname} : Run only the specified units.
20+
* -v : Do code coverage.
2021
*/
2122

2223
if(defined('STDIN') && function_exists( 'getopt' ) ) {
23-
$shortopts = 'u::d::c::t::r::oi';
24+
$shortopts = 'u::d::c::t::r::o::vi';
2425
$options = getopt($shortopts);
2526
}
2627
if(!isset($options) || !$options) {
2728
$options = array();
2829
}
2930
global $querystring_options;
3031
if(!isset($querystring_options)) {
31-
$querystring_options = array_intersect_key($_GET, array('o'=>1,'t'=>'','c'=>'','d'=>'','u'=>'','i'=>1));
32+
$querystring_options = array_intersect_key($_GET, array('o'=>1,'t'=>'','c'=>'','d'=>'','u'=>'','i'=>1,'v'=>''));
3233
$options = array_merge($options, $querystring_options);
3334
}
3435

@@ -131,6 +132,17 @@ public function assert_identical($value1, $value2, $message = 'Assertion failed'
131132
}
132133
}
133134

135+
public function assert_not_identical($value1, $value2, $message = 'Assertion failed')
136+
{
137+
if($value1 === $value2) {
138+
$this->messages[] = array(self::FAIL, $message, debug_backtrace());
139+
$this->fail_count++;
140+
}
141+
else {
142+
$this->pass_count++;
143+
}
144+
}
145+
134146
public function assert_exception($exception = '', $message = 'Expected exception')
135147
{
136148
$this->asserted_exception = array($exception, $message);
@@ -250,6 +262,10 @@ public function run()
250262
$this->module_setup();
251263
}
252264

265+
if(isset($options['v'])) {
266+
xdebug_start_code_coverage( XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE );
267+
}
268+
253269
// If specific tests are specified to run within this unit, get that list
254270
if(isset($options['t'])) {
255271
$options['t'] = explode(',', $options['t']);
@@ -375,7 +391,13 @@ public function run()
375391

376392
$this->result->case_count++;
377393
}
378-
394+
395+
if(isset($options['v'])) {
396+
$this->result->record_code_coverage(xdebug_get_code_coverage());
397+
398+
xdebug_stop_code_coverage();
399+
}
400+
379401
if(method_exists($this, 'module_teardown')) {
380402
$this->module_teardown();
381403
}
@@ -515,6 +537,8 @@ class TestResult
515537
public $file = '';
516538
public $summaries = array();
517539
private $options = array();
540+
private $type;
541+
public $code_coverage = array();
518542

519543
function __construct($test_name, $file = null)
520544
{
@@ -562,6 +586,21 @@ function summary($values)
562586
{
563587
$this->summaries = array_merge($this->summaries, $values);
564588
}
589+
590+
function record_code_coverage($coverage)
591+
{
592+
foreach($coverage as $filename => $lines) {
593+
if(!isset($this->code_coverage[$filename])) {
594+
$this->code_coverage[$filename] = array();
595+
}
596+
foreach($lines as $line_number => $result) {
597+
if(isset($this->code_coverage[$filename][$line_number])) {
598+
$result = max($this->code_coverage[$filename][$line_number], $result);
599+
}
600+
$this->code_coverage[$filename][$line_number] = $result;
601+
}
602+
}
603+
}
565604
}
566605

567606

@@ -689,6 +728,71 @@ function out_html()
689728
$output .= "<div class=\"test complete\"><p>{$summary['case_count']}/{$summary['total_case_count']} tests complete. {$summary['fail_count']} failed assertions. {$summary['pass_count']} passed assertions. {$summary['exception_count']} exceptions. {$summary['incomplete_count']} incomplete tests. {$summary['skipped_count']} skipped tests.</p></div>";
690729
}
691730

731+
if( count($test->code_coverage) ) {
732+
ksort($test->code_coverage);
733+
$output .= '<h1>Code Coverage</h1>';
734+
735+
// @todo what about @covers comments?
736+
// @todo and @codeCoverageIgnore, @codeCoverageIgnoreStart, and @codeCoverageIgnoreEnd?
737+
$file_id = 0;
738+
foreach ( $test->code_coverage as $file => $coverage ) {
739+
740+
$file_id++;
741+
$output .= '<h4>'. $file . '</h4>';
742+
743+
if(!file_exists($file)) {
744+
$output .= '<div>File could not be opened to display coverage.</div>';
745+
continue;
746+
}
747+
$lines = file( $file );
748+
749+
$output_file = '';
750+
$executed = 0;
751+
$executable = 0;
752+
$inaccessible = 0;
753+
754+
$output_file .= '<table class="coverage" id="coverage_' . $file_id . '">';
755+
for($i = 0; $i < count($lines); $i++) {
756+
$line_number = $i + 1;
757+
$line = $lines[$i];
758+
if ( isset($coverage[$line_number]) ) {
759+
$result = $coverage[$line_number];
760+
if ( $result == -2 && (trim($line) != '}') ) { // This code is inaccessible
761+
$class = 'inaccessible';
762+
$inaccessible++;
763+
$executable++;
764+
}
765+
else if ( $result > 0 ) { // This code executed
766+
$class = 'executed';
767+
$executed++;
768+
$executable++;
769+
}
770+
else if ( $result == -1 ) { // This code did not execute
771+
$class = 'unexecuted';
772+
$executable++;
773+
}
774+
else {
775+
$class = 'whitespace';
776+
}
777+
}
778+
else {
779+
$class = 'unknown';
780+
}
781+
$output_file .= "<tr><td class=\"line_number\">{$line_number}</td><td class=\"codeline {$class}\">" . htmlentities( $line ) . "</td></tr>";
782+
}
783+
$output_file .= '</table>';
784+
785+
$output .= '<details><summary>' . $executed . ' executed';
786+
if($inaccessible > 0) {
787+
$output .= ', ' . $inaccessible . ' inaccessible';
788+
}
789+
$pct = round($executed * 100 / $executable);
790+
$output .= ' out of ' . $executable . ' lines -- ' . $pct . '%</summary>';
791+
$output .= $output_file;
792+
$output .= '</details>';
793+
}
794+
}
795+
692796
$output .= '<footer><h3>Results</h3>';
693797
$output.= sprintf('<div class="all test complete">%d units containing %d tests. %d failed assertions. %d passed assertions. %d exceptions. %d incomplete tests. %d skipped tests.</div>', $this->count(), $totals['case_count'], $totals['fail_count'], $totals['pass_count'], $totals['exception_count'], $totals['incomplete_count'], $totals['skipped_count']);
694798

@@ -855,6 +959,10 @@ function out_symbolic()
855959
$xunit->addAttribute('pass', $summary['pass_count']);
856960
$xunit->addAttribute('exception', $summary['exception_count']);
857961
$xunit->addAttribute('incomplete', $summary['incomplete_count']);
962+
/*
963+
$coverage = $this->code_coverage[0]; // this part here doesn't work yet.
964+
$xunit->addAttribute('coverage', $coverage ); // the admin page doesn't do anything with this yet.
965+
*/
858966
}
859967

860968
foreach($timers as $k => $v) {
@@ -872,10 +980,15 @@ function out_symbolic()
872980
return $xml->asXML();
873981
}
874982

983+
function summary($test, $values)
984+
{
985+
$this->summaries[$test] = $values;
986+
}
987+
875988
}
876989

877990
include HABARI_PATH . '/index.php';
878991

879992
endif;
880993

881-
?>
994+
?>

code_coverage.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
include 'bootstrap.php';
4+
5+
// prevent it from running
6+
UnitTestCase::$run_all = true;
7+
8+
include( 'test_multibyte_native.php' );
9+
10+
// now let it run
11+
UnitTestCase::$run_all = false;
12+
13+
$results = MultiByteNativeTest::run_one('MultiByteNativeTest');
14+
15+
echo '<pre>';
16+
$results->code_coverage();
17+
echo '</pre>';
18+
19+
?>

style.css

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,30 @@ div.all:before {
5151
font-weight: normal;
5252
color: #999;
5353
}
54+
table {
55+
font: 13px "Consolas", monospace;
56+
color: black;
57+
}
58+
.line_number {
59+
text-align: right;
60+
padding-right: 5px;
61+
}
62+
.codeline {
63+
white-space: pre;
64+
}
65+
.executed {
66+
color: white;
67+
font-weight: bold;
68+
background-color: green;
69+
}
70+
.unexecuted {
71+
color: red;
72+
background-color: #dddddd;
73+
}
74+
.inaccessible {
75+
color: #990000;
76+
background-color: #ff8888;
77+
}
78+
.whitespace {
79+
color: #dadadb;
80+
}

0 commit comments

Comments
 (0)