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.4 API

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