mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-01-18 18:46:17 +00:00
aggregate code coverage for groups
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6760 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
parent
3263c0bc81
commit
44fae51ce8
6 changed files with 342 additions and 53 deletions
|
@ -456,3 +456,18 @@ div.code-coverage-results div.end {
|
|||
div.code-coverage-results div.realstart {
|
||||
margin-top:0px;
|
||||
}
|
||||
div.code-coverage-results p.note {
|
||||
color:#bbb;
|
||||
padding:5px;
|
||||
margin:5px 0 10px;
|
||||
font-size:10px;
|
||||
}
|
||||
div.code-coverage-results span.result-bad {
|
||||
color: #a00;
|
||||
}
|
||||
div.code-coverage-results span.result-ok {
|
||||
color: #fa0;
|
||||
}
|
||||
div.code-coverage-results span.result-good {
|
||||
color: #0a0;
|
||||
}
|
|
@ -123,9 +123,17 @@ if (isset($_GET['group'])) {
|
|||
if ('all' == $_GET['group']) {
|
||||
TestManager::runAllTests(CakeTestsGetReporter());
|
||||
} else {
|
||||
TestManager::runGroupTest(ucfirst($_GET['group']), CakeTestsGetReporter());
|
||||
if ($analyzeCodeCoverage) {
|
||||
CodeCoverageManager::start($_GET['group'], CakeTestsGetReporter());
|
||||
}
|
||||
TestManager::runGroupTest(ucfirst($_GET['group']), CakeTestsGetReporter());
|
||||
if ($analyzeCodeCoverage) {
|
||||
CodeCoverageManager::report();
|
||||
}
|
||||
}
|
||||
|
||||
CakePHPTestRunMore();
|
||||
CakePHPTestAnalyzeCodeCoverage();
|
||||
} elseif (isset($_GET['case'])) {
|
||||
|
||||
if ($analyzeCodeCoverage) {
|
||||
|
|
|
@ -247,6 +247,13 @@ class TestSuiteShell extends Shell {
|
|||
return TestManager::runAllTests($reporter);
|
||||
}
|
||||
|
||||
if ($this->doCoverage) {
|
||||
if (!extension_loaded('xdebug')) {
|
||||
$this->out('You must install Xdebug to use the CakePHP(tm) Code Coverage Analyzation. Download it from http://www.xdebug.org/docs/install');
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->type == 'group') {
|
||||
$ucFirstGroup = ucfirst($this->file);
|
||||
|
||||
|
@ -257,7 +264,15 @@ class TestSuiteShell extends Shell {
|
|||
$path = APP.'plugins'.DS.$this->category.DS.'tests'.DS.'groups';
|
||||
}
|
||||
|
||||
return TestManager::runGroupTest($ucFirstGroup, $reporter);
|
||||
if ($this->doCoverage) {
|
||||
require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
|
||||
CodeCoverageManager::start($ucFirstGroup, $reporter);
|
||||
}
|
||||
$result = TestManager::runGroupTest($ucFirstGroup, $reporter);
|
||||
if ($this->doCoverage) {
|
||||
CodeCoverageManager::report();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
$case = 'libs'.DS.$this->file.'.test.php';
|
||||
|
@ -268,11 +283,6 @@ class TestSuiteShell extends Shell {
|
|||
}
|
||||
|
||||
if ($this->doCoverage) {
|
||||
if (!extension_loaded('xdebug')) {
|
||||
$this->out('You must install Xdebug to use the CakePHP(tm) Code Coverage Analyzation. Download it from http://www.xdebug.org/docs/install');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
|
||||
CodeCoverageManager::start($case, $reporter);
|
||||
}
|
||||
|
@ -317,6 +327,9 @@ class TestSuiteShell extends Shell {
|
|||
} elseif ($this->category == 'app') {
|
||||
$_GET['app'] = true;
|
||||
}
|
||||
if ($this->type == 'group') {
|
||||
$_GET['group'] = true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* tries to install simpletest and exits gracefully if it is not there
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
/* SVN FILE: $Id: http_socket.test.php 6563 2008-03-12 21:19:31Z phpnut $ */
|
||||
/* SVN FILE: $Id: code_coverage_manager.test.php 6563 2008-03-12 21:19:31Z phpnut $ */
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
|
@ -230,7 +230,7 @@ PHP;
|
|||
43 => -1,
|
||||
);
|
||||
$execCodeLines = range(0, 72);
|
||||
$result = explode("</div>", $report = $manager->reportHtml($testObjectFile, $coverageData, $execCodeLines));
|
||||
$result = explode("</div>", $report = $manager->reportCaseHtml($testObjectFile, $coverageData, $execCodeLines));
|
||||
|
||||
foreach ($result as $num => $line) {
|
||||
$num++;
|
||||
|
@ -483,7 +483,7 @@ PHP;
|
|||
72 => 'ignored show end',
|
||||
);
|
||||
$execCodeLines = range(0, 72);
|
||||
$result = explode("</div>", $report = $manager->reportHtmlDiff($testObjectFile, $coverageData, $execCodeLines, 3));
|
||||
$result = explode("</div>", $report = $manager->reportCaseHtmlDiff($testObjectFile, $coverageData, $execCodeLines, 3));
|
||||
|
||||
foreach ($result as $line) {
|
||||
preg_match('/<span class="line-num">(.*?)<\/span>/', $line, $matches);
|
||||
|
|
|
@ -46,6 +46,13 @@ class CodeCoverageManager {
|
|||
* @var string
|
||||
*/
|
||||
var $pluginTest = false;
|
||||
/**
|
||||
* Is this a grouptest?
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $groupTest = false;
|
||||
/**
|
||||
* The test case file to analyze
|
||||
*
|
||||
|
@ -98,7 +105,9 @@ class CodeCoverageManager {
|
|||
if (isset($_GET['app'])) {
|
||||
$manager->appTest = true;
|
||||
}
|
||||
|
||||
if (isset($_GET['group'])) {
|
||||
$manager->groupTest = true;
|
||||
}
|
||||
if (isset($_GET['plugin'])) {
|
||||
$manager->pluginTest = Inflector::underscore($_GET['plugin']);
|
||||
}
|
||||
|
@ -114,6 +123,7 @@ class CodeCoverageManager {
|
|||
function report($output = true) {
|
||||
$manager =& CodeCoverageManager::getInstance();
|
||||
|
||||
if (!$manager->groupTest) {
|
||||
$testObjectFile = $manager->__testObjectFileFromCaseFile($manager->testCaseFile, $manager->appTest);
|
||||
|
||||
if (!file_exists($testObjectFile)) {
|
||||
|
@ -136,17 +146,55 @@ class CodeCoverageManager {
|
|||
|
||||
$execCodeLines = $manager->__getExecutableLines(file_get_contents($testObjectFile));
|
||||
$result = '';
|
||||
|
||||
switch (get_class($manager->reporter)) {
|
||||
case 'CakeHtmlReporter':
|
||||
$result = $manager->reportHtmlDiff(@file($testObjectFile), $coverageData, $execCodeLines, $manager->numDiffContextLines);
|
||||
$result = $manager->reportCaseHtmlDiff(@file($testObjectFile), $coverageData, $execCodeLines, $manager->numDiffContextLines);
|
||||
break;
|
||||
case 'CLIReporter':
|
||||
$result = $manager->reportCli(@file($testObjectFile), $coverageData, $execCodeLines, $manager->numDiffContextLines);
|
||||
$result = $manager->reportCaseCli(@file($testObjectFile), $coverageData, $execCodeLines, $manager->numDiffContextLines);
|
||||
break;
|
||||
default:
|
||||
trigger_error('Currently only HTML reporting is supported for code coverage analysis.');
|
||||
trigger_error('Currently only HTML and CLI reporting is supported for code coverage analysis.');
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$testObjectFiles = $manager->__testObjectFilesFromGroupFile($manager->testCaseFile, $manager->appTest);
|
||||
|
||||
foreach ($testObjectFiles as $file) {
|
||||
if (!file_exists($file)) {
|
||||
trigger_error('This test object file is invalid: '.$file);
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
$dump = xdebug_get_code_coverage();
|
||||
$coverageData = array();
|
||||
foreach ($dump as $file => $data) {
|
||||
if (in_array($file, $testObjectFiles)) {
|
||||
$coverageData[$file] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($coverageData) && $output) {
|
||||
echo 'The test object files are never loaded.';
|
||||
}
|
||||
|
||||
$execCodeLines = $manager->__getExecutableLines($testObjectFiles);
|
||||
$result = '';
|
||||
|
||||
switch (get_class($manager->reporter)) {
|
||||
case 'CakeHtmlReporter':
|
||||
$result = $manager->reportGroupHtml($testObjectFiles, $coverageData, $execCodeLines, $manager->numDiffContextLines);
|
||||
break;
|
||||
case 'CLIReporter':
|
||||
$result = $manager->reportGroupCli($testObjectFiles, $coverageData, $execCodeLines, $manager->numDiffContextLines);
|
||||
break;
|
||||
default:
|
||||
trigger_error('Currently only HTML and CLI reporting is supported for code coverage analysis.');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($output) {
|
||||
echo $result;
|
||||
|
@ -161,7 +209,7 @@ class CodeCoverageManager {
|
|||
* @param string $output
|
||||
* @return void
|
||||
*/
|
||||
function reportHtml($testObjectFile, $coverageData, $execCodeLines) {
|
||||
function reportCaseHtml($testObjectFile, $coverageData, $execCodeLines) {
|
||||
$manager = CodeCoverageManager::getInstance();
|
||||
$lineCount = $coveredCount = 0;
|
||||
$report = '';
|
||||
|
@ -198,7 +246,7 @@ class CodeCoverageManager {
|
|||
* @param string $output
|
||||
* @return void
|
||||
*/
|
||||
function reportHtmlDiff($testObjectFile, $coverageData, $execCodeLines, $numContextLines) {
|
||||
function reportCaseHtmlDiff($testObjectFile, $coverageData, $execCodeLines, $numContextLines) {
|
||||
$manager = CodeCoverageManager::getInstance();
|
||||
$total = count($testObjectFile);
|
||||
$lines = array();
|
||||
|
@ -316,7 +364,7 @@ class CodeCoverageManager {
|
|||
* @param string $output
|
||||
* @return void
|
||||
*/
|
||||
function reportCli($testObjectFile, $coverageData, $execCodeLines) {
|
||||
function reportCaseCli($testObjectFile, $coverageData, $execCodeLines) {
|
||||
$manager = CodeCoverageManager::getInstance();
|
||||
$lineCount = $coveredCount = 0;
|
||||
$report = '';
|
||||
|
@ -338,6 +386,85 @@ class CodeCoverageManager {
|
|||
|
||||
return $manager->__paintHeaderCli($lineCount, $coveredCount, $report);
|
||||
}
|
||||
/**
|
||||
* Diff reporting
|
||||
*
|
||||
* @param string $testObjectFile
|
||||
* @param string $coverageData
|
||||
* @param string $execCodeLines
|
||||
* @param string $output
|
||||
* @return void
|
||||
*/
|
||||
function reportGroupHtml($testObjectFiles, $coverageData, $execCodeLines, $numContextLines) {
|
||||
$manager = CodeCoverageManager::getInstance();
|
||||
$report = '';
|
||||
|
||||
foreach ($testObjectFiles as $testObjectFile) {
|
||||
$lineCount = $coveredCount = 0;
|
||||
$objFilename = $testObjectFile;
|
||||
$testObjectFile = file($testObjectFile);
|
||||
|
||||
foreach ($testObjectFile as $num => $line) {
|
||||
$num++;
|
||||
|
||||
$foundByManualFinder = array_key_exists($num, $execCodeLines[$objFilename]) && trim($execCodeLines[$objFilename][$num]) != '';
|
||||
$foundByXdebug = array_key_exists($num, $coverageData[$objFilename]) && $coverageData[$objFilename][$num] !== -2;
|
||||
|
||||
if ($foundByManualFinder && $foundByXdebug) {
|
||||
$class = 'uncovered';
|
||||
$lineCount++;
|
||||
|
||||
if ($coverageData[$objFilename][$num] > 0) {
|
||||
$class = 'covered';
|
||||
$coveredCount++;
|
||||
}
|
||||
} else {
|
||||
$class = 'ignored';
|
||||
}
|
||||
}
|
||||
|
||||
$report .= $manager->__paintGroupResultLine($objFilename, $lineCount, $coveredCount);
|
||||
}
|
||||
return $manager->__paintGroupResultHeader($report);
|
||||
}
|
||||
/**
|
||||
* CLI reporting
|
||||
*
|
||||
* @param string $testObjectFile
|
||||
* @param string $coverageData
|
||||
* @param string $execCodeLines
|
||||
* @param string $output
|
||||
* @return void
|
||||
*/
|
||||
function reportGroupCli($testObjectFiles, $coverageData, $execCodeLines) {
|
||||
$manager = CodeCoverageManager::getInstance();
|
||||
$report = '';
|
||||
|
||||
foreach ($testObjectFiles as $testObjectFile) {
|
||||
$lineCount = $coveredCount = 0;
|
||||
$objFilename = $testObjectFile;
|
||||
$testObjectFile = file($testObjectFile);
|
||||
|
||||
foreach ($testObjectFile as $num => $line) {
|
||||
$num++;
|
||||
|
||||
$foundByManualFinder = array_key_exists($num, $execCodeLines[$objFilename]) && trim($execCodeLines[$objFilename][$num]) != '';
|
||||
$foundByXdebug = array_key_exists($num, $coverageData[$objFilename]) && $coverageData[$objFilename][$num] !== -2;
|
||||
|
||||
if ($foundByManualFinder && $foundByXdebug) {
|
||||
$lineCount++;
|
||||
|
||||
if ($coverageData[$objFilename][$num] > 0) {
|
||||
$coveredCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$report .= $manager->__paintGroupResultLineCli($objFilename, $lineCount, $coveredCount);
|
||||
}
|
||||
|
||||
return $report;
|
||||
}
|
||||
/**
|
||||
* Returns the name of the test object file based on a given test case file name
|
||||
*
|
||||
|
@ -348,15 +475,7 @@ class CodeCoverageManager {
|
|||
*/
|
||||
function __testObjectFileFromCaseFile($file, $isApp = true) {
|
||||
$manager = CodeCoverageManager::getInstance();
|
||||
|
||||
$path = ROOT.DS;
|
||||
if ($isApp) {
|
||||
$path .= APP_DIR.DS;
|
||||
} elseif (!!$manager->pluginTest) {
|
||||
$path .= APP_DIR.DS.'plugins'.DS.$manager->pluginTest.DS;
|
||||
} else {
|
||||
$path = ROOT.DS.'cake'.DS;
|
||||
}
|
||||
$path = $manager->__getTestFilesPath($isApp);
|
||||
|
||||
$folderPrefixMap = array(
|
||||
'behaviors' => 'models',
|
||||
|
@ -388,6 +507,53 @@ class CodeCoverageManager {
|
|||
|
||||
return $path;
|
||||
}
|
||||
/**
|
||||
* Returns an array of names of the test object files based on a given test group file name
|
||||
*
|
||||
* @param array $files
|
||||
* @param string $isApp
|
||||
* @return array names of the test object files
|
||||
* @access private
|
||||
*/
|
||||
function __testObjectFilesFromGroupFile($groupFile, $isApp = true) {
|
||||
$manager = CodeCoverageManager::getInstance();
|
||||
$testManager =& new TestManager();
|
||||
|
||||
$path = TESTS.'groups';
|
||||
if (!$isApp) {
|
||||
$path = ROOT.DS.'cake'.DS.'tests'.DS.'groups';
|
||||
}
|
||||
if (!!$manager->pluginTest) {
|
||||
$path = APP.'plugins'.DS.$manager->pluginTest.DS.'tests'.DS.'groups';
|
||||
}
|
||||
$path .= DS.$groupFile.$testManager->_groupExtension;
|
||||
|
||||
if (!file_exists($path)) {
|
||||
trigger_error('This group file does not exist!');
|
||||
return array();
|
||||
}
|
||||
|
||||
$groupContent = file_get_contents($path);
|
||||
$ds = '\s*\.\s*DS\s*\.\s*';
|
||||
$pluginTest = 'APP\.\'plugins\''.$ds.'\''.$manager->pluginTest.'\''.$ds.'\'tests\''.$ds.'\'cases\'';
|
||||
$pattern = '/\s*TestManager::addTestFile\(\s*\$this,\s*('.$pluginTest.'|APP_TEST_CASES|CORE_TEST_CASES)'.$ds.'(.*?)\)/i';
|
||||
preg_match_all($pattern, $groupContent, $matches);
|
||||
|
||||
$result = array();
|
||||
foreach ($matches[2] as $file) {
|
||||
$patterns = array(
|
||||
'/\s*\.\s*DS\s*\.\s*/',
|
||||
'/\s*APP_TEST_CASES\s*/',
|
||||
'/\s*CORE_TEST_CASES\s*/',
|
||||
);
|
||||
$replacements = array(DS, '', '');
|
||||
$file = preg_replace($patterns, $replacements, $file);
|
||||
$file = r("'", '', $file);
|
||||
$result[] = $manager->__testObjectFileFromCaseFile($file, $isApp).'.php';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* Parses a given code string into an array of lines and replaces some non-executable code lines with the needed
|
||||
* amount of new lines in order for the code line numbers to stay in sync
|
||||
|
@ -397,6 +563,15 @@ class CodeCoverageManager {
|
|||
* @access private
|
||||
*/
|
||||
function __getExecutableLines($content) {
|
||||
if (is_array($content)) {
|
||||
$manager = CodeCoverageManager::getInstance();
|
||||
$result = array();
|
||||
foreach ($content as $file) {
|
||||
$result[$file] = $manager->__getExecutableLines(file_get_contents($file));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
$content = h($content);
|
||||
|
||||
// arrays are 0-indexed, but we want 1-indexed stuff now as we are talking code lines mind you (**)
|
||||
|
@ -444,6 +619,57 @@ class CodeCoverageManager {
|
|||
return $report = '<h2>Code Coverage: '.$codeCoverage.'%</h2>
|
||||
<div class="code-coverage-results"><pre>'.$report.'</pre></div>';
|
||||
}
|
||||
/**
|
||||
* Displays a notification concerning group test results
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function __paintGroupResultHeader($report) {
|
||||
return '<div class="code-coverage-results"><p class="note">Please keep in mind that the coverage can vary a little bit depending on how much the different tests in the group interfere. If for example, TEST A calls a line from TEST OBJECT B, the coverage for TEST OBJECT B will be a little greater than if you were running the corresponding test case for TEST OBJECT B alone.</p><pre>'.$report.'</pre></div>';
|
||||
}
|
||||
/**
|
||||
* Paints the headline for code coverage analysis
|
||||
*
|
||||
* @param string $codeCoverage
|
||||
* @param string $report
|
||||
* @return void
|
||||
* @access private
|
||||
*/
|
||||
function __paintGroupResultLine($file, $lineCount, $coveredCount) {
|
||||
$manager =& CodeCoverageManager::getInstance();
|
||||
$codeCoverage = $manager->__calcCoverage($lineCount, $coveredCount);
|
||||
|
||||
$class = 'result-bad';
|
||||
if ($codeCoverage > 50) {
|
||||
$class = 'result-ok';
|
||||
}
|
||||
if ($codeCoverage > 80) {
|
||||
$class = 'result-good';
|
||||
}
|
||||
return '<p>Code Coverage for '.$file.': <span class="'.$class.'">'.$codeCoverage.'%</span></p>';
|
||||
}
|
||||
/**
|
||||
* Paints the headline for code coverage analysis
|
||||
*
|
||||
* @param string $codeCoverage
|
||||
* @param string $report
|
||||
* @return void
|
||||
* @access private
|
||||
*/
|
||||
function __paintGroupResultLineCli($file, $lineCount, $coveredCount) {
|
||||
$manager =& CodeCoverageManager::getInstance();
|
||||
$codeCoverage = $manager->__calcCoverage($lineCount, $coveredCount);
|
||||
|
||||
$class = 'bad';
|
||||
if ($codeCoverage > 50) {
|
||||
$class = 'ok';
|
||||
}
|
||||
if ($codeCoverage > 80) {
|
||||
$class = 'good';
|
||||
}
|
||||
return "\n".'Code Coverage for '.$file.': '.$codeCoverage.'% ('.$class.')'."\n";
|
||||
}
|
||||
/**
|
||||
* Paints the headline for code coverage analysis in the CLI
|
||||
*
|
||||
|
@ -487,6 +713,26 @@ class CodeCoverageManager {
|
|||
? round(100*$coveredCount/$lineCount, 2)
|
||||
: '0.00';
|
||||
}
|
||||
/**
|
||||
* Gets us the base path to look for the test files
|
||||
*
|
||||
* @param string $isApp
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function __getTestFilesPath($isApp = true) {
|
||||
$manager = CodeCoverageManager::getInstance();
|
||||
$path = ROOT.DS;
|
||||
if ($isApp) {
|
||||
$path .= APP_DIR.DS;
|
||||
} elseif (!!$manager->pluginTest) {
|
||||
$path .= APP_DIR.DS.'plugins'.DS.$manager->pluginTest.DS;
|
||||
} else {
|
||||
$path = ROOT.DS.'cake'.DS;
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
/**
|
||||
* Finds the last element of an array that contains $needle in a strpos computation
|
||||
*
|
||||
|
|
|
@ -458,9 +458,16 @@ if (function_exists('caketestsgetreporter')) {
|
|||
} elseif (isset($_GET['plugin'])) {
|
||||
$query .= '&plugin=' . $_GET['plugin'];
|
||||
}
|
||||
} else {
|
||||
$query = '?group='.$_GET['group'];
|
||||
if (isset($_GET['app'])) {
|
||||
$query .= '&app=true';
|
||||
} elseif (isset($_GET['plugin'])) {
|
||||
$query .= '&plugin=' . $_GET['plugin'];
|
||||
}
|
||||
}
|
||||
$query .= '&code_coverage=true';
|
||||
echo "<p><a href='" . RUN_TEST_LINK . $query . "'>Analyze Code Coverage</a></p>\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue