From 5e29cfc21e0ffd20ebfee790ddf41520da1ab2f7 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 13 May 2010 21:36:23 -0400 Subject: [PATCH] Adding TextCoverageReport and extracting a base class. Updating the coverage classes to use the new class structure. --- .../lib/coverage/base_coverage_report.php | 175 ++++++++++++++++++ .../lib/coverage/html_coverage_report.php | 133 +------------ .../lib/coverage/text_coverage_report.php | 74 ++++++++ .../tests/lib/reporter/cake_text_reporter.php | 6 +- 4 files changed, 258 insertions(+), 130 deletions(-) create mode 100644 cake/tests/lib/coverage/base_coverage_report.php create mode 100644 cake/tests/lib/coverage/text_coverage_report.php diff --git a/cake/tests/lib/coverage/base_coverage_report.php b/cake/tests/lib/coverage/base_coverage_report.php new file mode 100644 index 000000000..5ef10a64e --- /dev/null +++ b/cake/tests/lib/coverage/base_coverage_report.php @@ -0,0 +1,175 @@ +_rawCoverage = $coverage; + $this->setParams($reporter); + } + +/** + * Pulls params out of the reporter. + * + * @param CakeBaseReporter $reporter Reporter to suck params out of. + * @return void + */ + protected function setParams(CakeBaseReporter $reporter) { + if ($reporter->params['app']) { + $this->appTest = true; + } + if ($reporter->params['group']) { + $this->groupTest = true; + } + if ($reporter->params['plugin']) { + $this->pluginTest = Inflector::underscore($reporter->params['plugin']); + } + } + +/** + * Set the coverage data array + * + * @param array $coverage Coverage data to use. + * @return void + */ + public function setCoverage($coverage) { + $this->_rawCoverage = $coverage; + } + +/** + * Gets the base path that the files we are interested in live in. + * If appTest ist + * + * @return void + */ + public function getPathFilter() { + $path = ROOT . DS; + if ($this->appTest) { + $path .= APP_DIR . DS; + } elseif ($this->pluginTest) { + $path = App::pluginPath($this->pluginTest); + } else { + $path = TEST_CAKE_CORE_INCLUDE_PATH; + } + return $path; + } + +/** + * Filters the coverage data by path. Files not in the provided path will be removed. + * This method will merge all the various test run reports as well into a single report per file. + * + * @param string $path Path to filter files by. + * @return array Array of coverage data for files that match the given path. + */ + public function filterCoverageDataByPath($path) { + $files = array(); + foreach ($this->_rawCoverage as $testRun) { + foreach ($testRun['files'] as $filename => $fileCoverage) { + if (strpos($filename, $path) !== 0) { + continue; + } + $dead = isset($testRun['dead'][$filename]) ? $testRun['dead'][$filename] : array(); + $executable = isset($testRun['executable'][$filename]) ? $testRun['executable'][$filename] : array(); + + if (!isset($files[$filename])) { + $files[$filename] = array( + 'covered' => array(), + 'dead' => array(), + 'executable' => array() + ); + } + $files[$filename]['covered'] += $fileCoverage; + $files[$filename]['executable'] += $executable; + $files[$filename]['dead'] += $dead; + } + if (isset($testRun['test'])) { + $testReflection = new ReflectionClass(get_class($testRun['test'])); + list($fileBasename, $x) = explode('.', basename($testReflection->getFileName()), 2); + $this->_testNames[] = $fileBasename; + } + } + ksort($files); + return $files; + } + +/** + * Generates report to display. + * + * @return string compiled html report. + */ + abstract public function report(); + +/** + * Generates an coverage 'diff' for $file based on $coverageData. + * + * @param string $filename Name of the file having coverage generated + * @param array $fileLines File data as an array. See file() for how to get one of these. + * @param array $coverageData Array of coverage data to use to generate HTML diffs with + * @return string prepared report for a single file. + */ + abstract public function generateDiff($filename, $fileLines, $coverageData); + +} \ No newline at end of file diff --git a/cake/tests/lib/coverage/html_coverage_report.php b/cake/tests/lib/coverage/html_coverage_report.php index 4d778e03e..c173aa068 100644 --- a/cake/tests/lib/coverage/html_coverage_report.php +++ b/cake/tests/lib/coverage/html_coverage_report.php @@ -17,79 +17,11 @@ * @since CakePHP(tm) v 2.0 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -class HtmlCoverageReport { -/** - * coverage data - * - * @var string - */ - protected $_rawCoverage; +require_once dirname(__FILE__) . '/base_coverage_report.php'; -/** - * is the test an app test - * - * @var string - */ - public $appTest = false; +PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'DEFAULT'); -/** - * is the test a plugin test - * - * @var string - */ - public $pluginTest = false; - -/** - * is the test a group test? - * - * @var string - */ - public $groupTest = false; - -/** - * Array of test case file names. Used to do basename() matching with - * files that have coverage to decide which results to show on page load. - * - * @var array - */ - protected $_testNames = array(); - -/** - * Constructor - * - * @param array $coverage Array of coverage data from PHPUnit_Test_Result - * @return void - */ - public function __construct($coverage, CakeBaseReporter $reporter) { - $this->_rawCoverage = $coverage; - $this->setParams($reporter); - } - -/** - * Pulls params out of the reporter. - * - * @return void - */ - protected function setParams(CakeBaseReporter $reporter) { - if ($reporter->params['app']) { - $this->appTest = true; - } - if ($reporter->params['group']) { - $this->groupTest = true; - } - if ($reporter->params['plugin']) { - $this->pluginTest = Inflector::underscore($reporter->params['plugin']); - } - } - -/** - * Set the coverage data array - * - * @return void - */ - public function setCoverage($coverage) { - $this->_rawCoverage = $coverage; - } +class HtmlCoverageReport extends BaseCoverageReport { /** * Generates report html to display. @@ -115,66 +47,11 @@ HTML; return $output; } -/** - * Gets the base path that the files we are interested in live in. - * If appTest ist - * - * @return void - */ - public function getPathFilter() { - $path = ROOT . DS; - if ($this->appTest) { - $path .= APP_DIR . DS; - } elseif ($this->pluginTest) { - $path = App::pluginPath($this->pluginTest); - } else { - $path = TEST_CAKE_CORE_INCLUDE_PATH; - } - return $path; - } - -/** - * Filters the coverage data by path. Files not in the provided path will be removed. - * This method will merge all the various test run reports as well into a single report per file. - * - * @param string $path Path to filter files by. - * @return array Array of coverage data for files that match the given path. - */ - public function filterCoverageDataByPath($path) { - $files = array(); - foreach ($this->_rawCoverage as $testRun) { - foreach ($testRun['files'] as $filename => $fileCoverage) { - if (strpos($filename, $path) !== 0) { - continue; - } - $dead = isset($testRun['dead'][$filename]) ? $testRun['dead'][$filename] : array(); - $executable = isset($testRun['executable'][$filename]) ? $testRun['executable'][$filename] : array(); - - if (!isset($files[$filename])) { - $files[$filename] = array( - 'covered' => array(), - 'dead' => array(), - 'executable' => array() - ); - } - $files[$filename]['covered'] += $fileCoverage; - $files[$filename]['executable'] += $executable; - $files[$filename]['dead'] += $dead; - } - if (isset($testRun['test'])) { - $testReflection = new ReflectionClass(get_class($testRun['test'])); - list($fileBasename, $x) = explode('.', basename($testReflection->getFileName()), 2); - $this->_testNames[] = $fileBasename; - } - } - ksort($files); - return $files; - } - /** * Generates an HTML diff for $file based on $coverageData. * - * @param array $fileData File data as an array. See file() for how to get one of these. + * @param string $filename Name of the file having coverage generated + * @param array $fileLines File data as an array. See file() for how to get one of these. * @param array $coverageData Array of coverage data to use to generate HTML diffs with * @return string HTML diff. */ diff --git a/cake/tests/lib/coverage/text_coverage_report.php b/cake/tests/lib/coverage/text_coverage_report.php new file mode 100644 index 000000000..bfe406b1b --- /dev/null +++ b/cake/tests/lib/coverage/text_coverage_report.php @@ -0,0 +1,74 @@ +getPathFilter(); + $coverageData = $this->filterCoverageDataByPath($pathFilter); + if (empty($coverageData)) { + return 'No files to generate coverage for'; + } + $output = "\nCoverage Report:\n\n"; + foreach ($coverageData as $file => $coverageData) { + $fileData = file($file); + $output .= $this->generateDiff($file, $fileData, $coverageData); + } + return $output; + } + +/** + * Generates a 'diff' report for a file. + * Since diffs are too big for plain text reports a simple file => % covered is done. + * + * @param string $filename Name of the file having coverage generated + * @param array $fileLines File data as an array. See file() for how to get one of these. + * @param array $coverageData Array of coverage data to use to generate HTML diffs with + * @return string + */ + public function generateDiff($filename, $fileLines, $coverageData) { + $covered = 0; + $total = 0; + + //shift line numbers forward one; + array_unshift($fileLines, ' '); + unset($fileLines[0]); + + foreach ($fileLines as $lineno => $line) { + if (isset($coverageData['covered'][$lineno])) { + $covered++; + $total++; + } elseif (isset($coverageData['executable'][$lineno])) { + $total++; + } + } + $percentCovered = round(100 * $covered / $total, 2); + return "$filename : $percentCovered%\n"; + } + +} \ No newline at end of file diff --git a/cake/tests/lib/reporter/cake_text_reporter.php b/cake/tests/lib/reporter/cake_text_reporter.php index 8f32b3c43..65eb03ed9 100644 --- a/cake/tests/lib/reporter/cake_text_reporter.php +++ b/cake/tests/lib/reporter/cake_text_reporter.php @@ -205,8 +205,10 @@ class CakeTextReporter extends CakeBaseReporter { * @return string */ public function paintCoverage($coverage) { - return ''; + $file = dirname(dirname(__FILE__)) . '/coverage/text_coverage_report.php'; + include $file; + $reporter = new TextCoverageReport($coverage, $this); + echo $reporter->report(); } } -?> \ No newline at end of file