CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 2.1 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.1
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Packages

  • Cake
    • Cache
      • Engine
    • Configure
    • Console
      • Command
        • Task
    • Controller
      • Component
        • Acl
        • Auth
    • Core
    • Error
    • Event
    • I18n
    • Log
      • Engine
    • Model
      • Behavior
      • Datasource
        • Database
        • Session
    • Network
      • Email
      • Http
    • Routing
      • Route
    • TestSuite
      • Coverage
      • Fixture
      • Reporter
    • Utility
    • View
      • Helper

Classes

  • BaseCoverageReport
  • HtmlCoverageReport
  • TextCoverageReport
  1: <?php
  2: /**
  3:  * Generates code coverage reports in HTML from data obtained from PHPUnit
  4:  *
  5:  * PHP5
  6:  *
  7:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  8:  * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9:  *
 10:  * Licensed under The MIT License
 11:  * Redistributions of files must retain the above copyright notice.
 12:  *
 13:  * @copyright     Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
 14:  * @link          http://cakephp.org CakePHP(tm) Project
 15:  * @package       Cake.TestSuite.Coverage
 16:  * @since         CakePHP(tm) v 2.0
 17:  * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
 18:  */
 19: 
 20: App::uses('BaseCoverageReport', 'TestSuite/Coverage');
 21: 
 22: /**
 23:  * Generates code coverage reports in HTML from data obtained from PHPUnit
 24:  *
 25:  * @package       Cake.TestSuite.Coverage
 26:  */
 27: class HtmlCoverageReport extends BaseCoverageReport {
 28: 
 29: /**
 30:  * Generates report html to display.
 31:  *
 32:  * @return string compiled html report.
 33:  */
 34:     public function report() {
 35:         $pathFilter = $this->getPathFilter();
 36:         $coverageData = $this->filterCoverageDataByPath($pathFilter);
 37:         if (empty($coverageData)) {
 38:             return '<h3>No files to generate coverage for</h3>';
 39:         }
 40:         $output = $this->coverageScript();
 41:         $output .= <<<HTML
 42:         <h3>Code coverage results
 43:         <a href="#" onclick="coverage_toggle_all()" class="coverage-toggle">Toggle all files</a>
 44:         </h3>
 45: HTML;
 46:         foreach ($coverageData as $file => $coverageData) {
 47:             $fileData = file($file);
 48:             $output .= $this->generateDiff($file, $fileData, $coverageData);
 49:         }
 50:         return $output;
 51:     }
 52: 
 53: /**
 54:  * Generates an HTML diff for $file based on $coverageData.
 55:  *
 56:  * Handles both PHPUnit3.5 and 3.6 formats.
 57:  *
 58:  * 3.5 uses -1 for uncovered, and -2 for dead.
 59:  * 3.6 uses array() for uncovered and null for dead.
 60:  *
 61:  * @param string $filename Name of the file having coverage generated
 62:  * @param array $fileLines File data as an array. See file() for how to get one of these.
 63:  * @param array $coverageData Array of coverage data to use to generate HTML diffs with
 64:  * @return string HTML diff.
 65:  */
 66:     public function generateDiff($filename, $fileLines, $coverageData) {
 67:         $output = '';
 68:         $diff = array();
 69: 
 70:         list($covered, $total) = $this->_calculateCoveredLines($fileLines, $coverageData);
 71: 
 72:         //shift line numbers forward one;
 73:         array_unshift($fileLines, ' ');
 74:         unset($fileLines[0]);
 75: 
 76:         foreach ($fileLines as $lineno => $line) {
 77:             $class = 'ignored';
 78:             $coveringTests = array();
 79:             if (!empty($coverageData[$lineno]) && is_array($coverageData[$lineno])) {
 80:                 $coveringTests = array();
 81:                 foreach ($coverageData[$lineno] as $test) {
 82:                     $class = (is_array($test) && isset($test['id'])) ? $test['id'] : $test;
 83:                     $testReflection = new ReflectionClass(current(explode('::', $class)));
 84:                     $this->_testNames[] = $this->_guessSubjectName($testReflection);
 85:                     $coveringTests[] = $class;
 86:                 }
 87:                 $class = 'covered';
 88:             } elseif (isset($coverageData[$lineno]) && ($coverageData[$lineno] === -1 || $coverageData[$lineno] === array())) {
 89:                 $class = 'uncovered';
 90:             } elseif (array_key_exists($lineno, $coverageData) && ($coverageData[$lineno] === -2 || $coverageData[$lineno] === null)) {
 91:                 $class .= ' dead';
 92:             }
 93:             $diff[] = $this->_paintLine($line, $lineno, $class, $coveringTests);
 94:         }
 95: 
 96:         $percentCovered = 100;
 97:         if ($total > 0) {
 98:             $percentCovered = round(100 * $covered / $total, 2);
 99:         }
100:         $output .= $this->coverageHeader($filename, $percentCovered);
101:         $output .= implode("", $diff);
102:         $output .= $this->coverageFooter();
103:         return $output;
104:     }
105: 
106: /**
107:  * Guess the classname the test was for based on the test case filename.
108:  *
109:  * @param ReflectionClass $testReflection.
110:  * @return string Possible test subject name.
111:  */
112:     protected function _guessSubjectName($testReflection) {
113:         $basename = basename($testReflection->getFilename());
114:         if (strpos($basename, '.test') !== false) {
115:             list($subject, ) = explode('.', $basename, 2);
116:             return $subject;
117:         }
118:         $subject = str_replace('Test.php', '', $basename);
119:         return $subject;
120:     }
121: 
122: /**
123:  * Renders the html for a single line in the html diff.
124:  *
125:  * @return void
126:  */
127:     protected function _paintLine($line, $linenumber, $class, $coveringTests) {
128:         $coveredBy = '';
129:         if (!empty($coveringTests)) {
130:             $coveredBy = "Covered by:\n";
131:             foreach ($coveringTests as $test) {
132:                 $coveredBy .= $test . "\n";
133:             }
134:         }
135: 
136:         return sprintf(
137:             '<div class="code-line %s" title="%s"><span class="line-num">%s</span><span class="content">%s</span></div>',
138:             $class,
139:             $coveredBy,
140:             $linenumber,
141:             htmlspecialchars($line)
142:         );
143:     }
144: 
145: /**
146:  * generate some javascript for the coverage report.
147:  *
148:  * @return void
149:  */
150:     public function coverageScript() {
151:         return <<<HTML
152:         <script type="text/javascript">
153:         function coverage_show_hide(selector) {
154:             var element = document.getElementById(selector);
155:             element.style.display = (element.style.display == 'none') ? '' : 'none';
156:         }
157:         function coverage_toggle_all() {
158:             var divs = document.querySelectorAll('div.coverage-container');
159:             var i = divs.length;
160:             while (i--) {
161:                 if (divs[i] && divs[i].className.indexOf('primary') == -1) {
162:                     divs[i].style.display = (divs[i].style.display == 'none') ? '' : 'none';
163:                 }
164:             }
165:         }
166:         </script>
167: HTML;
168:     }
169: 
170: /**
171:  * Generate an HTML snippet for coverage headers
172:  *
173:  * @return void
174:  */
175:     public function coverageHeader($filename, $percent) {
176:         $filename = basename($filename);
177:         list($file, $ext) = explode('.', $filename);
178:         $display = in_array($file, $this->_testNames) ? 'block' : 'none';
179:         $primary = $display == 'block' ? 'primary' : '';
180:         return <<<HTML
181:     <div class="coverage-container $primary" style="display:$display;">
182:     <h4>
183:         <a href="#coverage-$filename" onclick="coverage_show_hide('coverage-$filename');">
184:             $filename Code coverage: $percent%
185:         </a>
186:     </h4>
187:     <div class="code-coverage-results" id="coverage-$filename" style="display:none;">
188:     <pre>
189: HTML;
190:     }
191: 
192: /**
193:  * Generate an HTML snippet for coverage footers
194:  *
195:  * @return void
196:  */
197:     public function coverageFooter() {
198:         return "</pre></div></div>";
199:     }
200: 
201: }
202: 
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs