mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-01-18 18:46:17 +00:00
code coverage analysis for cli,
fixing CliReporter extending SimpleReporter and not TextReporter (to enable the printing of exceptions in cli) some minor refactorings git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6735 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
parent
e38afee93d
commit
f9ec1e752d
4 changed files with 135 additions and 34 deletions
|
@ -62,6 +62,13 @@ class TestSuiteShell extends Shell {
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
var $isPluginTest = false;
|
var $isPluginTest = false;
|
||||||
|
/**
|
||||||
|
* Stores if the user wishes to get a code coverage analysis report
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
var $doCoverage = false;
|
||||||
/**
|
/**
|
||||||
* Initialization method installs Simpletest and loads all plugins
|
* Initialization method installs Simpletest and loads all plugins
|
||||||
*
|
*
|
||||||
|
@ -82,7 +89,10 @@ class TestSuiteShell extends Shell {
|
||||||
require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_manager.php';
|
require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_manager.php';
|
||||||
require_once CAKE . 'tests' . DS . 'lib' . DS . 'cli_reporter.php';
|
require_once CAKE . 'tests' . DS . 'lib' . DS . 'cli_reporter.php';
|
||||||
|
|
||||||
$this->plugins = Configure::listObjects('plugin');
|
$plugins = Configure::listObjects('plugin');
|
||||||
|
foreach ($plugins as $p) {
|
||||||
|
$this->plugins[] = Inflector::underscore($p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Main entry point to this shell
|
* Main entry point to this shell
|
||||||
|
@ -106,7 +116,15 @@ class TestSuiteShell extends Shell {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->args[2])) {
|
if (isset($this->args[2])) {
|
||||||
$this->file = Inflector::underscore($this->args[2]);
|
if ($this->args[2] == 'cov') {
|
||||||
|
$this->doCoverage = true;
|
||||||
|
} else {
|
||||||
|
$this->file = Inflector::underscore($this->args[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->args[3]) && $this->args[3] == 'cov') {
|
||||||
|
$this->doCoverage = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->err('Sorry, you did not pass any arguments!');
|
$this->err('Sorry, you did not pass any arguments!');
|
||||||
|
@ -150,6 +168,11 @@ class TestSuiteShell extends Shell {
|
||||||
$this->out('');
|
$this->out('');
|
||||||
$this->out("\t\t cake testsuite bugs case models/bug // for the plugin 'bugs' and its test case 'bug'");
|
$this->out("\t\t cake testsuite bugs case models/bug // for the plugin 'bugs' and its test case 'bug'");
|
||||||
$this->out("\t\t cake testsuite bugs group bug // for the plugin bugs and its test group 'bug'");
|
$this->out("\t\t cake testsuite bugs group bug // for the plugin bugs and its test group 'bug'");
|
||||||
|
$this->out("\t\t cake testsuite bugs_me case models/bug // for the plugin 'bugs_me' and its test case 'bug'");
|
||||||
|
$this->out("\t\t cake testsuite bugs_me group bug // for the plugin bugs_me and its test group 'bug'");
|
||||||
|
$this->out('');
|
||||||
|
$this->out('Code Coverage Analysis: ');
|
||||||
|
$this->out("\n\nAppend 'gov' to any of the above in order to enable code coverage analysis");
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Checks if the arguments supplied point to a valid test file and thus the shell can be run.
|
* Checks if the arguments supplied point to a valid test file and thus the shell can be run.
|
||||||
|
@ -159,9 +182,9 @@ class TestSuiteShell extends Shell {
|
||||||
*/
|
*/
|
||||||
function __canRun(){
|
function __canRun(){
|
||||||
$isNeitherAppNorCore = !in_array($this->category, array('app', 'core'));
|
$isNeitherAppNorCore = !in_array($this->category, array('app', 'core'));
|
||||||
$isNotPlugin = !in_array(Inflector::humanize($this->category), $this->plugins);
|
$isPlugin = in_array(Inflector::underscore($this->category), $this->plugins);
|
||||||
|
|
||||||
if ($isNeitherAppNorCore && $isNotPlugin) {
|
if ($isNeitherAppNorCore && !$isPlugin) {
|
||||||
$this->err($this->category.' is an invalid test category (either "app", "core" or name of a plugin)');
|
$this->err($this->category.' is an invalid test category (either "app", "core" or name of a plugin)');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +196,7 @@ class TestSuiteShell extends Shell {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in_array($this->type, array('all', 'group', 'case'))) {
|
if (!in_array($this->type, array('all', 'group', 'case'))) {
|
||||||
$this->err($this->category.' is invalid. Should be case, group or all');
|
$this->err($this->type.' is invalid. Should be case, group or all');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +218,7 @@ class TestSuiteShell extends Shell {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$isNotPlugin && file_exists($folder.DS.'cases'.DS.$this->file.'.test.php')) {
|
if ($isPlugin && file_exists($folder.DS.'cases'.DS.$this->file.'.test.php')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -237,7 +260,22 @@ class TestSuiteShell extends Shell {
|
||||||
} elseif ($this->isPluginTest) {
|
} elseif ($this->isPluginTest) {
|
||||||
$case = $this->file.'.test.php';
|
$case = $this->file.'.test.php';
|
||||||
}
|
}
|
||||||
return TestManager::runTestCase($case, $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);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
|
||||||
|
CodeCoverageManager::start($case, $reporter);
|
||||||
|
}
|
||||||
|
$result = TestManager::runTestCase($case, $reporter);
|
||||||
|
if ($this->doCoverage) {
|
||||||
|
CodeCoverageManager::report();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Finds the correct folder to look for tests for based on the input category
|
* Finds the correct folder to look for tests for based on the input category
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
|
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
|
||||||
*/
|
*/
|
||||||
App::import('Core', 'CodeCoverageManager');
|
App::import('Core', 'CodeCoverageManager');
|
||||||
|
require_once CAKE . 'tests' . DS . 'lib' . DS . 'cli_reporter.php';
|
||||||
|
require_once CAKE . 'tests' . DS . 'lib' . DS . 'cake_reporter.php';
|
||||||
/**
|
/**
|
||||||
* Short description for class.
|
* Short description for class.
|
||||||
*
|
*
|
||||||
|
@ -39,34 +41,41 @@ class CodeCoverageManagerTest extends UnitTestCase {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function testNoTestCaseSupplied() {
|
function testNoTestCaseSupplied() {
|
||||||
CodeCoverageManager::start(substr(md5(microtime()), 0, 5), CakeTestsGetReporter());
|
if (php_sapi_name() != 'cli') { // assertError seems to be not working for cli reports
|
||||||
CodeCoverageManager::report(false);
|
CodeCoverageManager::start(substr(md5(microtime()), 0, 5), new CakeHtmlReporter);
|
||||||
$this->assertError();
|
|
||||||
|
|
||||||
CodeCoverageManager::start('libs/'.basename(__FILE__), CakeTestsGetReporter());
|
|
||||||
CodeCoverageManager::report(false);
|
|
||||||
$this->assertError();
|
|
||||||
|
|
||||||
App::import('Core', 'Folder');
|
|
||||||
$folder = new Folder();
|
|
||||||
$folder->cd(ROOT.DS.LIBS);
|
|
||||||
$contents = $folder->ls();
|
|
||||||
function remove($var) {
|
|
||||||
return ($var != basename(__FILE__));
|
|
||||||
}
|
|
||||||
$contents[1] = array_filter($contents[1], "remove");
|
|
||||||
$keys = array_rand($contents[1], 5);
|
|
||||||
|
|
||||||
foreach ($keys as $key) {
|
|
||||||
CodeCoverageManager::start('libs'.DS.$contents[1][$key], CakeTestsGetReporter());
|
|
||||||
CodeCoverageManager::report(false);
|
CodeCoverageManager::report(false);
|
||||||
$this->assertNoErrors();
|
$this->assertError();
|
||||||
|
|
||||||
|
CodeCoverageManager::start('libs/'.basename(__FILE__), new CakeHtmlReporter);
|
||||||
|
CodeCoverageManager::report(false);
|
||||||
|
$this->assertError();
|
||||||
|
|
||||||
|
$path = LIBS;
|
||||||
|
if (strpos(LIBS, ROOT) === false) { // cli fix
|
||||||
|
$path = ROOT.DS.LIBS;
|
||||||
|
}
|
||||||
|
App::import('Core', 'Folder');
|
||||||
|
$folder = new Folder();
|
||||||
|
$folder->cd($path);
|
||||||
|
$contents = $folder->ls();
|
||||||
|
|
||||||
|
function remove($var) {
|
||||||
|
return ($var != basename(__FILE__));
|
||||||
|
}
|
||||||
|
$contents[1] = array_filter($contents[1], "remove");
|
||||||
|
$keys = array_rand($contents[1], 5);
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
CodeCoverageManager::start('libs'.DS.$contents[1][$key], new CakeHtmlReporter);
|
||||||
|
CodeCoverageManager::report(false);
|
||||||
|
$this->assertNoErrors();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetTestObjectFileNameFromTestCaseFile() {
|
function testGetTestObjectFileNameFromTestCaseFile() {
|
||||||
$manager = CodeCoverageManager::getInstance();
|
$manager = CodeCoverageManager::getInstance();
|
||||||
|
|
||||||
|
$manager->reporter = new CakeHtmlReporter;
|
||||||
$expected = $manager->__testObjectFileFromCaseFile('models/some_file.test.php', true);
|
$expected = $manager->__testObjectFileFromCaseFile('models/some_file.test.php', true);
|
||||||
$this->assertIdentical(APP.'models'.DS.'some_file.php', $expected);
|
$this->assertIdentical(APP.'models'.DS.'some_file.php', $expected);
|
||||||
|
|
||||||
|
@ -88,6 +97,11 @@ class CodeCoverageManagerTest extends UnitTestCase {
|
||||||
$manager->pluginTest = 'bugs';
|
$manager->pluginTest = 'bugs';
|
||||||
$expected = $manager->__testObjectFileFromCaseFile('models/some_file.test.php', false);
|
$expected = $manager->__testObjectFileFromCaseFile('models/some_file.test.php', false);
|
||||||
$this->assertIdentical(APP.'plugins'.DS.'bugs'.DS.'models'.DS.'some_file.php', $expected);
|
$this->assertIdentical(APP.'plugins'.DS.'bugs'.DS.'models'.DS.'some_file.php', $expected);
|
||||||
|
|
||||||
|
$manager->pluginTest = false;
|
||||||
|
$manager->reporter = new CLIReporter;
|
||||||
|
$expected = $manager->__testObjectFileFromCaseFile('libs/set.test.php', false);
|
||||||
|
$this->assertIdentical(ROOT.DS.'cake'.DS.'libs'.DS.'set.php', $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testOfHtmlReport() {
|
function testOfHtmlReport() {
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
* @package cake
|
* @package cake
|
||||||
* @subpackage cake.cake.tests.libs
|
* @subpackage cake.cake.tests.libs
|
||||||
*/
|
*/
|
||||||
class CLIReporter extends SimpleReporter {
|
class CLIReporter extends TextReporter {
|
||||||
var $faildetail_separator = ST_FAILDETAIL_SEPARATOR;
|
var $faildetail_separator = ST_FAILDETAIL_SEPARATOR;
|
||||||
|
|
||||||
function CLIReporter($faildetail_separator = NULL) {
|
function CLIReporter($faildetail_separator = NULL) {
|
||||||
|
|
|
@ -90,6 +90,7 @@ class CodeCoverageManager {
|
||||||
$manager->reporter = $reporter;
|
$manager->reporter = $reporter;
|
||||||
|
|
||||||
$thisFile = r('.php', '.test.php', basename(__FILE__));
|
$thisFile = r('.php', '.test.php', basename(__FILE__));
|
||||||
|
|
||||||
if (strpos($testCaseFile, $thisFile) !== false) {
|
if (strpos($testCaseFile, $thisFile) !== false) {
|
||||||
trigger_error('Xdebug supports no parallel coverage analysis - so this is not possible.', E_USER_ERROR);
|
trigger_error('Xdebug supports no parallel coverage analysis - so this is not possible.', E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -97,9 +98,9 @@ class CodeCoverageManager {
|
||||||
if (isset($_GET['app'])) {
|
if (isset($_GET['app'])) {
|
||||||
$manager->appTest = true;
|
$manager->appTest = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_GET['plugin'])) {
|
if (isset($_GET['plugin'])) {
|
||||||
$manager->pluginTest = $_GET['plugin'];
|
$manager->pluginTest = Inflector::underscore($_GET['plugin']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$manager->testCaseFile = $testCaseFile;
|
$manager->testCaseFile = $testCaseFile;
|
||||||
|
@ -114,8 +115,9 @@ class CodeCoverageManager {
|
||||||
$manager =& CodeCoverageManager::getInstance();
|
$manager =& CodeCoverageManager::getInstance();
|
||||||
|
|
||||||
$testObjectFile = $manager->__testObjectFileFromCaseFile($manager->testCaseFile, $manager->appTest);
|
$testObjectFile = $manager->__testObjectFileFromCaseFile($manager->testCaseFile, $manager->appTest);
|
||||||
|
|
||||||
if (!file_exists($testObjectFile)) {
|
if (!file_exists($testObjectFile)) {
|
||||||
trigger_error('This test object file is invalid.');
|
trigger_error('This test object file is invalid: '.$testObjectFile);
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +140,9 @@ class CodeCoverageManager {
|
||||||
case 'CakeHtmlReporter':
|
case 'CakeHtmlReporter':
|
||||||
$result = $manager->reportHtmlDiff(@file($testObjectFile), $coverageData, $execCodeLines, $manager->numDiffContextLines);
|
$result = $manager->reportHtmlDiff(@file($testObjectFile), $coverageData, $execCodeLines, $manager->numDiffContextLines);
|
||||||
break;
|
break;
|
||||||
|
case 'CLIReporter':
|
||||||
|
$result = $manager->reportCli(@file($testObjectFile), $coverageData, $execCodeLines, $manager->numDiffContextLines);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
trigger_error('Currently only HTML reporting is supported for code coverage analysis.');
|
trigger_error('Currently only HTML reporting is supported for code coverage analysis.');
|
||||||
break;
|
break;
|
||||||
|
@ -175,7 +180,6 @@ class CodeCoverageManager {
|
||||||
if ($coverageData[$num] > 0) {
|
if ($coverageData[$num] > 0) {
|
||||||
$class = 'covered';
|
$class = 'covered';
|
||||||
$coveredCount++;
|
$coveredCount++;
|
||||||
$numExecuted = $coverageData[$num];
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$class = 'ignored';
|
$class = 'ignored';
|
||||||
|
@ -303,6 +307,37 @@ class CodeCoverageManager {
|
||||||
|
|
||||||
return $manager->__paintHeader($lineCount, $coveredCount, $report);
|
return $manager->__paintHeader($lineCount, $coveredCount, $report);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* CLI reporting
|
||||||
|
*
|
||||||
|
* @param string $testObjectFile
|
||||||
|
* @param string $coverageData
|
||||||
|
* @param string $execCodeLines
|
||||||
|
* @param string $output
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function reportCli($testObjectFile, $coverageData, $execCodeLines) {
|
||||||
|
$manager = CodeCoverageManager::getInstance();
|
||||||
|
$lineCount = $coveredCount = 0;
|
||||||
|
$report = '';
|
||||||
|
|
||||||
|
foreach ($testObjectFile as $num => $line) {
|
||||||
|
$num++;
|
||||||
|
|
||||||
|
$foundByManualFinder = array_key_exists($num, $execCodeLines) && trim($execCodeLines[$num]) != '';
|
||||||
|
$foundByXdebug = array_key_exists($num, $coverageData) && $coverageData[$num] !== -2;
|
||||||
|
|
||||||
|
if ($foundByManualFinder && $foundByXdebug) {
|
||||||
|
$lineCount++;
|
||||||
|
|
||||||
|
if ($coverageData[$num] > 0) {
|
||||||
|
$coveredCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $manager->__paintHeaderCli($lineCount, $coveredCount, $report);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns the name of the test object file based on a given test case file name
|
* Returns the name of the test object file based on a given test case file name
|
||||||
*
|
*
|
||||||
|
@ -320,7 +355,7 @@ class CodeCoverageManager {
|
||||||
} elseif (!!$manager->pluginTest) {
|
} elseif (!!$manager->pluginTest) {
|
||||||
$path .= APP_DIR.DS.'plugins'.DS.$manager->pluginTest.DS;
|
$path .= APP_DIR.DS.'plugins'.DS.$manager->pluginTest.DS;
|
||||||
} else {
|
} else {
|
||||||
$path .= CAKE;
|
$path = ROOT.DS.'cake'.DS;
|
||||||
}
|
}
|
||||||
|
|
||||||
$folderPrefixMap = array(
|
$folderPrefixMap = array(
|
||||||
|
@ -409,6 +444,20 @@ class CodeCoverageManager {
|
||||||
return $report = '<h2>Code Coverage: '.$codeCoverage.'%</h2>
|
return $report = '<h2>Code Coverage: '.$codeCoverage.'%</h2>
|
||||||
<div class="code-coverage-results"><pre>'.$report.'</pre></div>';
|
<div class="code-coverage-results"><pre>'.$report.'</pre></div>';
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Paints the headline for code coverage analysis in the CLI
|
||||||
|
*
|
||||||
|
* @param string $codeCoverage
|
||||||
|
* @param string $report
|
||||||
|
* @return void
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function __paintHeaderCli($lineCount, $coveredCount, $report) {
|
||||||
|
$manager =& CodeCoverageManager::getInstance();
|
||||||
|
$codeCoverage = $manager->__calcCoverage($lineCount, $coveredCount);
|
||||||
|
|
||||||
|
return $report = 'Code Coverage: '.$codeCoverage.'%';
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Paints a code line for html output
|
* Paints a code line for html output
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Reference in a new issue