Merge branch '1.3-test-suite' into 1.3-misc

This commit is contained in:
Mark Story 2010-01-12 09:31:07 -05:00
commit 8e22e8cbea
18 changed files with 1389 additions and 1035 deletions

View file

@ -18,7 +18,6 @@
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
set_time_limit(0);
ini_set('memory_limit','128M');
ini_set('display_errors', 1);
/**
* Use the DS to separate the directories in other defines
@ -85,89 +84,13 @@ if (isset($corePath[0])) {
define('TEST_CAKE_CORE_INCLUDE_PATH', CAKE_CORE_INCLUDE_PATH);
}
require_once CAKE_TESTS_LIB . 'test_manager.php';
if (Configure::read('debug') < 1) {
die(__('Debug setting does not allow access to this url.', true));
}
if (!isset($_SERVER['SERVER_NAME'])) {
$_SERVER['SERVER_NAME'] = '';
}
if (empty( $_GET['output'])) {
$_GET['output'] = 'html';
}
/**
*
* Used to determine output to display
*/
define('CAKE_TEST_OUTPUT_HTML', 1);
define('CAKE_TEST_OUTPUT_TEXT', 2);
require_once CAKE_TESTS_LIB . 'cake_test_suite_dispatcher.php';
if (isset($_GET['output']) && $_GET['output'] == 'html') {
define('CAKE_TEST_OUTPUT', CAKE_TEST_OUTPUT_HTML);
} else {
Debugger::output('txt');
define('CAKE_TEST_OUTPUT', CAKE_TEST_OUTPUT_TEXT);
}
$Dispatcher = new CakeTestSuiteDispatcher();
$Dispatcher->dispatch();
if (!App::import('Vendor', 'simpletest' . DS . 'reporter')) {
CakePHPTestHeader();
include CAKE_TESTS_LIB . 'simpletest.php';
CakePHPTestSuiteFooter();
exit();
}
$analyzeCodeCoverage = false;
if (isset($_GET['code_coverage'])) {
$analyzeCodeCoverage = true;
require_once CAKE_TESTS_LIB . 'code_coverage_manager.php';
if (!extension_loaded('xdebug')) {
CakePHPTestHeader();
include CAKE_TESTS_LIB . 'xdebug.php';
CakePHPTestSuiteFooter();
exit();
}
}
CakePHPTestHeader();
CakePHPTestSuiteHeader();
define('RUN_TEST_LINK', $_SERVER['PHP_SELF']);
if (isset($_GET['group'])) {
if ('all' == $_GET['group']) {
TestManager::runAllTests(CakeTestsGetReporter());
} else {
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) {
CodeCoverageManager::start($_GET['case'], CakeTestsGetReporter());
}
TestManager::runTestCase($_GET['case'], CakeTestsGetReporter());
if ($analyzeCodeCoverage) {
CodeCoverageManager::report();
}
CakePHPTestRunMore();
CakePHPTestAnalyzeCodeCoverage();
} elseif (isset($_GET['show']) && $_GET['show'] == 'cases') {
CakePHPTestCaseList();
} else {
CakePHPTestGroupTestList();
}
CakePHPTestSuiteFooter();
$output = ob_get_clean();
echo $output;
?>

View file

@ -69,14 +69,6 @@ class TestSuiteShell extends Shell {
*/
var $doCoverage = false;
/**
* The headline for the test output
*
* @var string
* @access public
*/
var $headline = 'CakePHP Test Shell';
/**
* Initialization method installs Simpletest and loads all plugins
*
@ -94,12 +86,60 @@ class TestSuiteShell extends Shell {
$this->__installSimpleTest();
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 . 'reporter' . DS . 'cake_cli_reporter.php';
$plugins = App::objects('plugin');
foreach ($plugins as $p) {
$this->plugins[] = Inflector::underscore($p);
}
$this->parseArgs();
$this->getManager();
}
/**
* Parse the arguments given into the Shell object properties.
*
* @return void
* @access public
*/
function parseArgs() {
if (empty($this->args)) {
return;
}
$this->category = $this->args[0];
if (!in_array($this->category, array('app', 'core'))) {
$this->isPluginTest = true;
}
if (isset($this->args[1])) {
$this->type = $this->args[1];
}
if (isset($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;
}
}
/**
* Gets a manager instance, and set the app/plugin properties.
*
* @return void
*/
function getManager() {
$this->Manager = new TestManager();
$this->Manager->appTest = ($this->category === 'app');
if ($this->isPluginTest) {
$this->Manager->pluginTest = $this->category;
}
}
/**
@ -109,46 +149,24 @@ class TestSuiteShell extends Shell {
* @access public
*/
function main() {
$this->out($this->headline);
$this->out(__('CakePHP Test Shell', true));
$this->hr();
if (count($this->args) > 0) {
$this->category = $this->args[0];
if (!in_array($this->category, array('app', 'core'))) {
$this->isPluginTest = true;
}
if (isset($this->args[1])) {
$this->type = $this->args[1];
}
if (isset($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 {
$this->err('Sorry, you did not pass any arguments!');
if (count($this->args) == 0) {
$this->error(__('Sorry, you did not pass any arguments!', true));
}
if ($this->__canRun()) {
$this->out('Running '.$this->category.' '.$this->type.' '.$this->file);
$message = sprintf(__('Running %s %s %s', true), $this->category, $this->type, $this->file);
$this->out($message);
$exitCode = 0;
if (!$this->__run()) {
$exitCode = 1;
}
exit($exitCode);
$this->_stop($exitCode);
} else {
$this->err('Sorry, the tests could not be found.');
exit(1);
$this->error(__('Sorry, the tests could not be found.', true));
}
}
@ -201,50 +219,37 @@ class TestSuiteShell extends Shell {
$isPlugin = in_array(Inflector::underscore($this->category), $this->plugins);
if ($isNeitherAppNorCore && !$isPlugin) {
$this->err($this->category.' is an invalid test category (either "app", "core" or name of a plugin)');
$message = sprintf(
__('%s is an invalid test category (either "app", "core" or name of a plugin)', true),
$this->category
);
$this->error($message);
return false;
}
$folder = $this->__findFolderByCategory($this->category);
if (!file_exists($folder)) {
$this->err($folder . ' not found');
$this->err(sprintf(__('%s not found', true), $folder));
return false;
}
if (!in_array($this->type, array('all', 'group', 'case'))) {
$this->err($this->type.' is invalid. Should be case, group or all');
$this->err(sprintf(__('%s is invalid. Should be case, group or all', true), $this->type));
return false;
}
switch ($this->type) {
case 'all':
return true;
break;
case 'group':
if (file_exists($folder.DS.'groups'.DS.$this->file.'.group.php')) {
return true;
}
break;
case 'case':
if ($this->category == 'app' && file_exists($folder.DS.'cases'.DS.$this->file.'.test.php')) {
return true;
}
$coreCaseExists = file_exists($folder.DS.'cases'.DS.$this->file.'.test.php');
$coreLibCaseExists = file_exists($folder.DS.'cases'.DS.'libs'.DS.$this->file.'.test.php');
if ($this->category == 'core' && ($coreCaseExists || $coreLibCaseExists)) {
return true;
}
if ($isPlugin && file_exists($folder.DS.'cases'.DS.$this->file.'.test.php')) {
return true;
}
break;
$fileName = $this->__getFileName($folder, $this->isPluginTest);
if ($fileName === true || file_exists($folder . $fileName)) {
return true;
}
$this->err($this->category.' '.$this->type.' '.$this->file.' is an invalid test identifier');
$message = sprintf(
__('%s %s %s is an invalid test identifier', true),
$this->category, $this->type, $this->file
);
$this->err($message);
return false;
}
/**
* Executes the tests depending on our settings
*
@ -252,69 +257,82 @@ class TestSuiteShell extends Shell {
* @access private
*/
function __run() {
$reporter = new CLIReporter();
$this->__setGetVars();
$Reporter = new CakeCliReporter('utf-8', array(
'app' => $this->Manager->appTest,
'plugin' => $this->Manager->pluginTest,
'group' => ($this->type === 'group'),
'codeCoverage' => $this->doCoverage
));
if ($this->type == 'all') {
return TestManager::runAllTests($reporter);
return $this->Manager->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);
$this->out(__('You must install Xdebug to use the CakePHP(tm) Code Coverage Analyzation. Download it from http://www.xdebug.org/docs/install', true));
$this->_stop(0);
}
}
if ($this->type == 'group') {
$ucFirstGroup = ucfirst($this->file);
$path = CORE_TEST_GROUPS;
if ($this->category == 'app') {
$path = APP_TEST_GROUPS;
} elseif ($this->isPluginTest) {
$path = APP.'plugins'.DS.$this->category.DS.'tests'.DS.'groups';
}
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();
CodeCoverageManager::init($ucFirstGroup, $Reporter);
CodeCoverageManager::start();
}
$result = $this->Manager->runGroupTest($ucFirstGroup, $Reporter);
return $result;
}
if ($this->category === 'core') {
$coreCaseExists = file_exists(CORE_TEST_CASES.DS.$this->file.'.test.php');
if ($coreCaseExists) {
$case = $this->file . '.test.php';
} else {
$case = 'libs' . DS . $this->file . '.test.php';
}
} elseif ($this->category === 'app') {
$case = $this->file.'.test.php';
} elseif ($this->isPluginTest) {
$case = $this->file.'.test.php';
}
$folder = $folder = $this->__findFolderByCategory($this->category);
$case = $this->__getFileName($folder, $this->isPluginTest);
if ($this->doCoverage) {
require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
CodeCoverageManager::start($case, $reporter);
CodeCoverageManager::init($case, $Reporter);
CodeCoverageManager::start();
}
$result = TestManager::runTestCase($case, $reporter);
if ($this->doCoverage) {
CodeCoverageManager::report();
}
$result = $this->Manager->runTestCase($case, $Reporter);
return $result;
}
/**
* Finds the correct folder to look for tests for based on the input category
* Gets the concrete filename for the inputted test name and category/type
*
* @param string $folder Folder name to look for files in.
* @param boolean $isPlugin If the test case is a plugin.
* @return mixed Either string filename or boolean false on failure. Or true if the type is 'all'
* @access private
*/
function __getFileName($folder, $isPlugin) {
$ext = $this->Manager->getExtension($this->type);
switch ($this->type) {
case 'all':
return true;
case 'group':
return $this->file . $ext;
case 'case':
if ($this->category == 'app' || $isPlugin) {
return $this->file . $ext;
}
$coreCase = $this->file . $ext;
$coreLibCase = 'libs' . DS . $this->file . $ext;
if ($this->category == 'core' && file_exists($folder . DS . $coreCase)) {
return $coreCase;
} elseif ($this->category == 'core' && file_exists($folder . DS . $coreLibCase)) {
return $coreLibCase;
}
}
return false;
}
/**
* Finds the correct folder to look for tests for based on the input category and type.
*
* @param string $category The category of the test. Either 'app', 'core' or a plugin name.
* @return string the folder path
* @access private
*/
@ -322,20 +340,16 @@ class TestSuiteShell extends Shell {
$folder = '';
$paths = array(
'core' => CAKE,
'app' => APP
'app' => APP
);
$typeDir = $this->type === 'group' ? 'groups' : 'cases';
if (array_key_exists($category, $paths)) {
$folder = $paths[$category] . 'tests';
$folder = $paths[$category] . 'tests' . DS . $typeDir . DS;
} else {
$scoredCategory = Inflector::underscore($category);
$folder = APP . 'plugins' . DS . $scoredCategory . DS;
$pluginPaths = App::path('plugins');
foreach ($pluginPaths as $path) {
if (file_exists($path . $scoredCategory . DS . 'tests')) {
$folder = $path . $scoredCategory . DS . 'tests';
break;
}
$pluginPath = App::pluginPath($category);
if (is_dir($pluginPath . 'tests')) {
$folder = $pluginPath . 'tests' . DS . $typeDir . DS;
}
}
return $folder;
@ -350,8 +364,8 @@ class TestSuiteShell extends Shell {
function __setGetVars() {
if (in_array($this->category, $this->plugins)) {
$_GET['plugin'] = $this->category;
} elseif (in_array(Inflector::Humanize($this->category), $this->plugins)) {
$_GET['plugin'] = Inflector::Humanize($this->category);
} elseif (in_array(Inflector::humanize($this->category), $this->plugins)) {
$_GET['plugin'] = Inflector::humanize($this->category);
} elseif ($this->category == 'app') {
$_GET['app'] = true;
}
@ -368,7 +382,7 @@ class TestSuiteShell extends Shell {
*/
function __installSimpleTest() {
if (!App::import('Vendor', 'simpletest' . DS . 'reporter')) {
$this->err('Sorry, Simpletest could not be found. Download it from http://simpletest.org and install it to your vendors directory.');
$this->err(__('Sorry, Simpletest could not be found. Download it from http://simpletest.org and install it to your vendors directory.', true));
exit;
}
}

View file

@ -19,7 +19,6 @@
*/
require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
require_once CAKE . 'tests' . DS . 'lib' . DS . 'cli_reporter.php';
require_once CAKE . 'tests' . DS . 'lib' . DS . 'cake_reporter.php';
/**
* CodeCoverageManagerTest class
@ -65,12 +64,13 @@ class CodeCoverageManagerTest extends CakeTestCase {
*/
function testNoTestCaseSupplied() {
if (PHP_SAPI != 'cli') {
unset($_GET['group']);
CodeCoverageManager::start(substr(md5(microtime()), 0, 5), new CakeHtmlReporter());
$reporter =& new CakeHtmlReporter(null, array('group' => false, 'app' => false, 'plugin' => false));
CodeCoverageManager::init(substr(md5(microtime()), 0, 5), $reporter);
CodeCoverageManager::report(false);
$this->assertError();
CodeCoverageManager::start('tests' . DS . 'lib' . DS . basename(__FILE__), new CakeHtmlReporter());
CodeCoverageManager::init('tests' . DS . 'lib' . DS . basename(__FILE__), $reporter);
CodeCoverageManager::report(false);
$this->assertError();
@ -96,7 +96,7 @@ class CodeCoverageManagerTest extends CakeTestCase {
$contents[1] = array_filter($contents[1], "remove");
foreach ($contents[1] as $file) {
CodeCoverageManager::start('libs'.DS.$file, new CakeHtmlReporter());
CodeCoverageManager::init('libs'.DS.$file, $reporter);
CodeCoverageManager::report(false);
$this->assertNoErrors('libs'.DS.$file);
}

View file

@ -19,7 +19,6 @@
* @since CakePHP(tm) v 1.2.0.4206
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
App::import('Core', 'TestManager');
/**
* TestManagerTest class
@ -36,7 +35,7 @@ class TestManagerTest extends CakeTestCase {
* @access public
*/
function setUp() {
$this->Sut =& new TestManager();
$this->TestManager =& new TestManager();
$this->Reporter =& new CakeHtmlReporter();
}
@ -47,12 +46,12 @@ class TestManagerTest extends CakeTestCase {
* @access public
*/
function testRunAllTests() {
$folder =& new Folder($this->Sut->_getTestsPath());
$extension = str_replace('.', '\.', TestManager::getExtension('test'));
$folder =& new Folder($this->TestManager->_getTestsPath());
$extension = str_replace('.', '\.', $this->TestManager->getExtension('test'));
$out = $folder->findRecursive('.*' . $extension);
$reporter =& new CakeHtmlReporter();
$list = TestManager::runAllTests($reporter, true);
$list = $this->TestManager->runAllTests($reporter, true);
$this->assertEqual(count($out), count($list));
}
@ -65,12 +64,12 @@ class TestManagerTest extends CakeTestCase {
*/
function testRunTestCase() {
$file = md5(time());
$result = $this->Sut->runTestCase($file, $this->Reporter);
$result = $this->TestManager->runTestCase($file, $this->Reporter);
$this->assertError('Test case ' . $file . ' cannot be found');
$this->assertFalse($result);
$file = str_replace(CORE_TEST_CASES, '', __FILE__);
$result = $this->Sut->runTestCase($file, $this->Reporter, true);
$result = $this->TestManager->runTestCase($file, $this->Reporter, true);
$this->assertTrue($result);
}

View file

@ -0,0 +1,249 @@
<?php
/**
* CakeTestSuiteDispatcher controls dispatching TestSuite web based requests.
*
* PHP versions 4 and 5
*
* CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
* Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The Open Group Test Suite License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org
* @package cake
* @subpackage cake.cake.tests.lib
* @since CakePHP(tm) v 1.3
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
require_once CAKE_TESTS_LIB . 'test_manager.php';
/**
* CakeTestSuiteDispatcher handles web requests to the test suite and runs the correct action.
*
* @package cake.tests.libs
*/
class CakeTestSuiteDispatcher {
/**
* 'Request' parameters
*
* @var array
*/
var $params = array(
'codeCoverage' => false,
'group' => null,
'case' => null,
'app' => false,
'plugin' => null,
'output' => 'html',
'show' => 'groups',
'show_passes' => false
);
/**
* The classname for the TestManager being used
*
* @var string
*/
var $_managerClass = 'TestManager';
/**
* The Instance of the Manager being used.
*
* @var TestManager subclass
*/
var $Manager;
/**
* Baseurl for the request
*
* @var string
*/
var $_baseUrl;
/**
* Base dir of the request. Used for accessing assets.
*
* @var string
*/
var $_baseDir;
/**
* constructor
*
* @return void
*/
function CakeTestSuiteDispatcher() {
$this->_baseUrl = $_SERVER['PHP_SELF'];
$this->_baseDir = dirname($this->_baseUrl) . '/';
}
/**
* Runs the actions required by the URL parameters.
*
* @return void
*/
function dispatch() {
$this->_checkSimpleTest();
$this->_parseParams();
if ($this->params['group']) {
$this->_runGroupTest();
} elseif ($this->params['case']) {
$this->_runTestCase();
} elseif (isset($_GET['show']) && $_GET['show'] == 'cases') {
$this->_testCaseList();
} else {
$this->_groupTestList();
}
$output = ob_get_clean();
echo $output;
}
/**
* Checks that simpleTest is installed. Will exit if it doesn't
*
* @return void
*/
function _checkSimpleTest() {
if (!App::import('Vendor', 'simpletest' . DS . 'reporter')) {
$basePath = $this->_baseDir;
include CAKE_TESTS_LIB . 'templates' . DS . 'simpletest.php';
exit();
}
}
/**
* Checks for the xdebug extension required to do code coverage. Displays an error
* if xdebug isn't installed.
*
* @return void
*/
function _checkXdebug() {
if (!extension_loaded('xdebug')) {
$basePath = $this->_baseDir;
include CAKE_TESTS_LIB . 'templates' . DS . 'xdebug.php';
exit();
}
}
/**
* Generates a page containing the a list of test cases that could be run.
*
* @return void
*/
function _testCaseList() {
$Reporter =& $this->getReporter();
$Reporter->paintDocumentStart();
$Reporter->paintTestMenu();
$Reporter->testCaseList();
$Reporter->paintDocumentEnd();
}
/**
* Generates a page containing a list of group tests that could be run.
*
* @return void
*/
function _groupTestList() {
$Reporter =& $this->getReporter();
$Reporter->paintDocumentStart();
$Reporter->paintTestMenu();
$Reporter->groupTestList();
$Reporter->paintDocumentEnd();
}
/**
* Sets the Manager to use for the request.
*
* @return string The manager class name
* @static
*/
function &getManager() {
if (empty($this->Manager)) {
$this->Manager = new $this->_managerClass();
}
return $this->Manager;
}
/**
* Gets the reporter based on the request parameters
*
* @return void
* @static
*/
function &getReporter() {
static $Reporter = NULL;
if (!$Reporter) {
$type = strtolower($this->params['output']);
$coreClass = 'Cake' . ucwords($this->params['output']) . 'Reporter';
$coreFile = CAKE_TESTS_LIB . 'reporter' . DS . 'cake_' . $type . '_reporter.php';
$appClass = $this->params['output'] . 'Reporter';
$appFile = APPLIBS . 'test_suite' . DS . 'reporter' . DS . $type . '_reporter.php';
if (include_once $coreFile) {
$Reporter =& new $coreClass(null, $this->params);
} elseif (include_once $appFile) {
$Reporter =& new $appClass(null, $this->params);
}
}
return $Reporter;
}
/**
* Parse url params into a 'request'
*
* @return void
*/
function _parseParams() {
if (!isset($_SERVER['SERVER_NAME'])) {
$_SERVER['SERVER_NAME'] = '';
}
foreach ($this->params as $key => $value) {
if (isset($_GET[$key])) {
$this->params[$key] = $_GET[$key];
}
}
if (isset($_GET['code_coverage'])) {
$this->params['codeCoverage'] = true;
require_once CAKE_TESTS_LIB . 'code_coverage_manager.php';
$this->_checkXdebug();
}
$this->params['baseUrl'] = $this->_baseUrl;
$this->params['baseDir'] = $this->_baseDir;
$this->getManager();
}
/**
* Runs the group test case.
*
* @return void
*/
function _runGroupTest() {
$Reporter =& CakeTestSuiteDispatcher::getReporter();
if ('all' == $this->params['group']) {
$this->Manager->runAllTests($Reporter);
} else {
if ($this->params['codeCoverage']) {
CodeCoverageManager::init($this->params['group'], $Reporter);
}
$this->Manager->runGroupTest(ucfirst($this->params['group']), $Reporter);
}
}
/**
* Runs a test case file.
*
* @return void
*/
function _runTestCase() {
$Reporter =& CakeTestSuiteDispatcher::getReporter();
if ($this->params['codeCoverage']) {
CodeCoverageManager::init($this->params['case'], $Reporter);
}
$this->Manager->runTestCase($this->params['case'], $Reporter);
}
}
?>

View file

@ -1,60 +0,0 @@
<?php
class CakeTextReporter extends TextReporter {
var $_timeStart = 0;
var $_timeEnd = 0;
var $_timeDuration = 0;
/**
* Signals / Paints the beginning of a TestSuite executing.
* Starts the timer for the TestSuite execution time.
*
* @param
* @return void
*/
function paintGroupStart($test_name, $size) {
if (empty($this->_timeStart)) {
$this->_timeStart = $this->_getTime();
}
parent::paintGroupStart($test_name, $size);
}
/**
* Signals/Paints the end of a TestSuite. All test cases have run
* and timers are stopped.
*
* @return void
*/
function paintGroupEnd($test_name) {
$this->_timeEnd = $this->_getTime();
$this->_timeDuration = $this->_timeEnd - $this->_timeStart;
parent::paintGroupEnd($test_name);
}
/**
* Get the current time in microseconds. Similar to getMicrotime in basics.php
* but in a separate function to reduce dependancies.
*
* @return float Time in microseconds
*/
function _getTime() {
list($usec, $sec) = explode(' ', microtime());
return ((float)$sec + (float)$usec);
}
/**
* Paints the end of the test with a summary of
* the passes and failures.
*
* @param string $test_name Name class of test.
* @access public
*/
function paintFooter($test_name) {
parent::paintFooter($test_name);
echo 'Time taken by tests (in seconds): ' . $this->_timeDuration . "\n";
if (function_exists('memory_get_peak_usage')) {
echo 'Peak memory use: (in bytes): ' . number_format(memory_get_peak_usage()) . "\n";
}
}
}
?>

View file

@ -1,101 +0,0 @@
<?php
/**
* Short description for file.
*
* PHP versions 4 and 5
*
* CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
* Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The Open Group Test Suite License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
* @package cake
* @subpackage cake.cake.tests.libs
* @since CakePHP(tm) v 1.2.0.4433
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
if (! defined('ST_FAILDETAIL_SEPARATOR')) {
define('ST_FAILDETAIL_SEPARATOR', "->");
}
if (version_compare(PHP_VERSION, '4.4.4', '<=') ||
PHP_SAPI == 'cgi') {
define('STDOUT', fopen('php://stdout', 'w'));
define('STDERR', fopen('php://stderr', 'w'));
register_shutdown_function(create_function('', 'fclose(STDOUT); fclose(STDERR); return true;'));
}
/**
* Minimal command line test displayer. Writes fail details to STDERR. Returns 0
* to the shell if all tests pass, ST_FAILS_RETURN_CODE if any test fails.
*
* @package cake
* @subpackage cake.cake.tests.libs
*/
class CLIReporter extends TextReporter {
var $faildetail_separator = ST_FAILDETAIL_SEPARATOR;
function CLIReporter($faildetail_separator = NULL) {
$this->SimpleReporter();
if (! is_null($faildetail_separator)) {
$this->setFailDetailSeparator($faildetail_separator);
}
}
function setFailDetailSeparator($separator) {
$this->faildetail_separator = $separator;
}
/**
* Return a formatted faildetail for printing.
*/
function &_paintTestFailDetail(&$message) {
$buffer = '';
$faildetail = $this->getTestList();
array_shift($faildetail);
$buffer .= implode($this->faildetail_separator, $faildetail);
$buffer .= $this->faildetail_separator . "$message\n";
return $buffer;
}
/**
* Paint fail faildetail to STDERR.
*/
function paintFail($message) {
parent::paintFail($message);
fwrite(STDERR, 'FAIL' . $this->faildetail_separator . $this->_paintTestFailDetail($message));
}
/**
* Paint exception faildetail to STDERR.
*/
function paintException($message) {
parent::paintException($message);
fwrite(STDERR, 'EXCEPTION' . $this->faildetail_separator . $this->_paintTestFailDetail($message));
}
/**
* Paint a footer with test case name, timestamp, counts of fails and exceptions.
*/
function paintFooter($test_name) {
$buffer = $this->getTestCaseProgress() . '/' . $this->getTestCaseCount() . ' test cases complete: ';
if (0 < ($this->getFailCount() + $this->getExceptionCount())) {
$buffer .= $this->getPassCount() . " passes";
if (0 < $this->getFailCount()) {
$buffer .= ", " . $this->getFailCount() . " fails";
}
if (0 < $this->getExceptionCount()) {
$buffer .= ", " . $this->getExceptionCount() . " exceptions";
}
$buffer .= ".\n";
fwrite(STDOUT, $buffer);
} else {
fwrite(STDOUT, $buffer . $this->getPassCount() . " passes.\n");
}
}
}
?>

View file

@ -87,67 +87,97 @@ class CodeCoverageManager {
}
/**
* Starts a new Coverage Analyzation for a given test case file
* @TODO: Works with $_GET now within the function body, which will make it hard when we do code coverage reports for CLI
* Initializes a new Coverage Analyzation for a given test case file
*
* @param string $testCaseFile
* @param string $reporter
* @param string $testCaseFile The test case file being covered.
* @param object $reporter Instance of the reporter running.
* @return void
* @static
*/
function start($testCaseFile, &$reporter) {
function init($testCaseFile, &$reporter) {
$manager =& CodeCoverageManager::getInstance();
$manager->reporter = $reporter;
$manager->reporter =& $reporter;
$testCaseFile = str_replace(DS . DS, DS, $testCaseFile);
$thisFile = str_replace('.php', '.test.php', basename(__FILE__));
if (strpos($testCaseFile, $thisFile) !== false) {
trigger_error('Xdebug supports no parallel coverage analysis - so this is not possible.', E_USER_ERROR);
}
if (isset($_GET['app'])) {
$manager->appTest = true;
}
if (isset($_GET['group'])) {
$manager->groupTest = true;
}
if (isset($_GET['plugin'])) {
$manager->pluginTest = Inflector::underscore($_GET['plugin']);
}
$manager->setParams($reporter);
$manager->testCaseFile = $testCaseFile;
}
/**
* Start/resume Code coverage collection.
*
* @return void
* @static
*/
function start() {
xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
}
/**
* Stops the current code coverage analyzation and dumps a nice report depending on the reporter that was passed to start()
* Stops/pauses code coverage collection. Does not clean the
* code coverage memory. Use clean() to clear code coverage memory
*
* @return void
* @static
*/
function stop() {
xdebug_stop_code_coverage(false);
}
/**
* Clears the existing code coverage information. Also stops any
* running collection.
*
* @return void
* @static
*/
function clear() {
xdebug_stop_code_coverage();
}
/**
* Set the parameters from a reporter to the CodeCoverageManager
*
* @return void
*/
function setParams(&$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']);
}
}
/**
* Stops the current code coverage analyzation and dumps a nice report
* depending on the reporter that was passed to start()
*
* @return void
* @static
*/
function report($output = true) {
$manager =& CodeCoverageManager::getInstance();
CodeCoverageManager::stop();
CodeCoverageManager::clear();
list($coverageData, $testObjectFile) = $manager->_getCoverageData();
if (empty($coverageData) && $output) {
echo "The test object file is never loaded.\n";
}
if (!$manager->groupTest) {
$testObjectFile = $manager->__testObjectFileFromCaseFile($manager->testCaseFile, $manager->appTest);
if (!file_exists($testObjectFile)) {
trigger_error('This test object file is invalid: ' . $testObjectFile);
return ;
}
$dump = xdebug_get_code_coverage();
xdebug_stop_code_coverage();
$coverageData = array();
foreach ($dump as $file => $data) {
if ($file == $testObjectFile) {
$coverageData = $data;
break;
}
}
if (empty($coverageData) && $output) {
echo 'The test object file is never loaded.';
}
$execCodeLines = $manager->__getExecutableLines(file_get_contents($testObjectFile));
$result = '';
@ -155,46 +185,22 @@ class CodeCoverageManager {
case 'CakeHtmlReporter':
$result = $manager->reportCaseHtmlDiff(@file($testObjectFile), $coverageData, $execCodeLines, $manager->numDiffContextLines);
break;
case 'CLIReporter':
$result = $manager->reportCaseCli(@file($testObjectFile), $coverageData, $execCodeLines, $manager->numDiffContextLines);
break;
case 'CakeCliReporter':
default:
trigger_error('Currently only HTML and CLI reporting is supported for code coverage analysis.');
$result = $manager->reportCaseCli(@file($testObjectFile), $coverageData, $execCodeLines, $manager->numDiffContextLines);
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();
xdebug_stop_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);
$execCodeLines = $manager->__getExecutableLines($testObjectFile);
$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);
$result = $manager->reportGroupHtml($testObjectFile, $coverageData, $execCodeLines, $manager->numDiffContextLines);
break;
case 'CakeCliReporter':
default:
trigger_error('Currently only HTML and CLI reporting is supported for code coverage analysis.');
$result = $manager->reportGroupCli($testObjectFile, $coverageData, $execCodeLines, $manager->numDiffContextLines);
break;
}
}
@ -205,39 +211,40 @@ class CodeCoverageManager {
}
/**
* Html reporting
* Gets the coverage data for the test case or group test that is being run.
*
* @param string $testObjectFile
* @param string $coverageData
* @param string $execCodeLines
* @param string $output
* @return void
*/
function reportCaseHtml($testObjectFile, $coverageData, $execCodeLines) {
$manager = CodeCoverageManager::getInstance();
$lineCount = $coveredCount = 0;
$report = '';
function _getCoverageData() {
$coverageData = array();
$dump = xdebug_get_code_coverage();
foreach ($testObjectFile as $num => $line) {
$num++;
$foundByManualFinder = isset($execCodeLines[$num]) && trim($execCodeLines[$num]) != '';
$foundByXdebug = isset($coverageData[$num]) && $coverageData[$num] !== -2;
// xdebug does not find all executable lines (zend engine fault)
if ($foundByManualFinder && $foundByXdebug) {
$class = 'uncovered';
$lineCount++;
if ($coverageData[$num] > 0) {
$class = 'covered';
$coveredCount++;
if ($this->groupTest) {
$testObjectFile = $this->__testObjectFilesFromGroupFile($this->testCaseFile, $this->appTest);
foreach ($testObjectFile as $file) {
if (!file_exists($file)) {
trigger_error('This test object file is invalid: ' . $file);
return ;
}
} else {
$class = 'ignored';
}
$report .= $manager->__paintCodeline($class, $num, $line);
foreach ($testObjectFile as $file) {
if (isset($dump[$file])) {
$coverageData[$file] = $dump[$file];
}
}
} else {
$testObjectFile = $this->__testObjectFileFromCaseFile($this->testCaseFile, $this->appTest);
if (!file_exists($testObjectFile)) {
trigger_error('This test object file is invalid: ' . $testObjectFile);
return ;
}
if (isset($dump[$testObjectFile])) {
$coverageData = $dump[$testObjectFile];
}
}
return $manager->__paintHeader($lineCount, $coveredCount, $report);
return array($coverageData, $testObjectFile);
}
/**
@ -248,6 +255,7 @@ class CodeCoverageManager {
* @param string $execCodeLines
* @param string $output
* @return void
* @static
*/
function reportCaseHtmlDiff($testObjectFile, $coverageData, $execCodeLines, $numContextLines) {
$manager = CodeCoverageManager::getInstance();
@ -366,6 +374,7 @@ class CodeCoverageManager {
* @param string $execCodeLines
* @param string $output
* @return void
* @static
*/
function reportCaseCli($testObjectFile, $coverageData, $execCodeLines) {
$manager = CodeCoverageManager::getInstance();
@ -396,6 +405,7 @@ class CodeCoverageManager {
* @param string $execCodeLines
* @param string $output
* @return void
* @static
*/
function reportGroupHtml($testObjectFiles, $coverageData, $execCodeLines, $numContextLines) {
$manager = CodeCoverageManager::getInstance();
@ -436,6 +446,7 @@ class CodeCoverageManager {
* @param string $execCodeLines
* @param string $output
* @return void
* @static
*/
function reportGroupCli($testObjectFiles, $coverageData, $execCodeLines) {
$manager = CodeCoverageManager::getInstance();
@ -670,7 +681,6 @@ class CodeCoverageManager {
$manager =& CodeCoverageManager::getInstance();
$codeCoverage = $manager->__calcCoverage($lineCount, $coveredCount);
$class = 'bad';
if ($codeCoverage > 50) {
$class = 'ok';
}
@ -691,7 +701,14 @@ class CodeCoverageManager {
function __paintHeaderCli($lineCount, $coveredCount, $report) {
$manager =& CodeCoverageManager::getInstance();
$codeCoverage = $manager->__calcCoverage($lineCount, $coveredCount);
return $report = 'Code Coverage: ' . $codeCoverage . '%';
$class = 'bad';
if ($codeCoverage > 50) {
$class = 'ok';
}
if ($codeCoverage > 80) {
$class = 'good';
}
return $report = "Code Coverage: $codeCoverage% ($class)\n";
}
/**

View file

@ -0,0 +1,226 @@
<?php
/**
* CakeBaseReporter contains common functionality to all cake test suite reporters.
*
* PHP versions 4 and 5
*
* CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
* Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The Open Group Test Suite License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org
* @package cake
* @subpackage cake.tests.libs.reporter
* @since CakePHP(tm) v 1.3
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
/**
* CakeBaseReporter contains common reporting features used in the CakePHP Test suite
*
* @package cake
* @subpackage cake.tests.lib
*/
class CakeBaseReporter extends SimpleReporter {
/**
* Time the test runs started.
*
* @var integer
* @access protected
*/
var $_timeStart = 0;
/**
* Time the test runs ended
*
* @var integer
* @access protected
*/
var $_timeEnd = 0;
/**
* Duration of all test methods.
*
* @var integer
* @access protected
*/
var $_timeDuration = 0;
/**
* Array of request parameters. Usually parsed GET params.
*
* @var array
*/
var $params = array();
/**
* Character set for the output of test reporting.
*
* @var string
* @access protected
*/
var $_characterSet;
/**
* Does nothing yet. The first output will
* be sent on the first test start.
*
* ### Params
*
* - show_passes - Should passes be shown
* - plugin - Plugin test being run?
* - app - App test being run.
* - case - The case being run
* - codeCoverage - Whether the case/group being run is being code covered.
*
* @param string $charset The character set to output with. Defaults to UTF-8
* @param array $params Array of request parameters the reporter should use. See above.
* @access public
*/
function CakeBaseReporter($charset = 'utf-8', $params = array()) {
$this->SimpleReporter();
if (!$charset) {
$charset = 'utf-8';
}
$this->_characterSet = $charset;
$this->params = $params;
}
/**
* Signals / Paints the beginning of a TestSuite executing.
* Starts the timer for the TestSuite execution time.
*
* @param string $test_name Name of the test that is being run.
* @param integer $size
* @return void
*/
function paintGroupStart($test_name, $size) {
if (empty($this->_timeStart)) {
$this->_timeStart = $this->_getTime();
}
parent::paintGroupStart($test_name, $size);
}
/**
* Signals/Paints the end of a TestSuite. All test cases have run
* and timers are stopped.
*
* @param string $test_name Name of the test that is being run.
* @return void
*/
function paintGroupEnd($test_name) {
$this->_timeEnd = $this->_getTime();
$this->_timeDuration = $this->_timeEnd - $this->_timeStart;
parent::paintGroupEnd($test_name);
}
/**
* Paints the beginning of a test method being run. This is used
* to start/resume the code coverage tool.
*
* @param string $method The method name being run.
* @return void
*/
function paintMethodStart($method) {
parent::paintMethodStart($method);
if (!empty($this->params['codeCoverage'])) {
CodeCoverageManager::start();
}
}
/**
* Paints the end of a test method being run. This is used
* to pause the collection of code coverage if its being used.
*
* @param string $method The name of the method being run.
* @return void
*/
function paintMethodEnd($method) {
parent::paintMethodEnd($method);
if (!empty($this->params['codeCoverage'])) {
CodeCoverageManager::stop();
}
}
/**
* Get the current time in microseconds. Similar to getMicrotime in basics.php
* but in a separate function to reduce dependancies.
*
* @return float Time in microseconds
* @access protected
*/
function _getTime() {
list($usec, $sec) = explode(' ', microtime());
return ((float)$sec + (float)$usec);
}
/**
* Retrieves a list of test cases from the active Manager class,
* displaying it in the correct format for the reporter subclass
*
* @return mixed
*/
function testCaseList() {
$testList = TestManager::getTestCaseList();
return $testList;
}
/**
* Retrieves a list of group test cases from the active Manager class
* displaying it in the correct format for the reporter subclass.
*
* @return void
*/
function groupTestList() {
$testList = TestManager::getGroupTestList();
return $testList;
}
/**
* Paints the start of the response from the test suite.
* Used to paint things like head elements in an html page.
*
* @return void
*/
function paintDocumentStart() {
}
/**
* Paints the end of the response from the test suite.
* Used to paint things like </body> in an html page.
*
* @return void
*/
function paintDocumentEnd() {
}
/**
* Paint a list of test sets, core, app, and plugin test sets
* available.
*
* @return void
*/
function paintTestMenu() {
}
/**
* Get the baseUrl if one is available.
*
* @return string The base url for the request.
*/
function baseUrl() {
if (!empty($_SERVER['PHP_SELF'])) {
return $_SERVER['PHP_SELF'];
}
return '';
}
}
?>

View file

@ -0,0 +1,179 @@
<?php
/**
* Cake CLI test reporter.
*
* PHP versions 4 and 5
*
* CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
* Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The Open Group Test Suite License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
* @package cake
* @subpackage cake.cake.tests.libs
* @since CakePHP(tm) v 1.2.0.4433
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
if (version_compare(PHP_VERSION, '4.4.4', '<=') ||
PHP_SAPI == 'cgi') {
define('STDOUT', fopen('php://stdout', 'w'));
define('STDERR', fopen('php://stderr', 'w'));
register_shutdown_function(create_function('', 'fclose(STDOUT); fclose(STDERR); return true;'));
}
include_once dirname(__FILE__) . DS . 'cake_base_reporter.php';
/**
* Minimal command line test displayer. Writes fail details to STDERR. Returns 0
* to the shell if all tests pass, ST_FAILS_RETURN_CODE if any test fails.
*
* @package cake
* @subpackage cake.tests.libs.reporter
*/
class CakeCliReporter extends CakeBaseReporter {
/**
* separator string for fail, error, exception, and skip messages.
*
* @var string
*/
var $separator = '->';
/**
* array of 'request' parameters
*
* @var array
*/
var $params = array();
/**
* Constructor
*
* @param string $separator
* @param array $params
* @return void
*/
function CakeCLIReporter($charset = 'utf-8', $params = array()) {
$this->CakeBaseReporter($charset, $params);
}
function setFailDetailSeparator($separator) {
$this->separator = $separator;
}
/**
* Paint fail faildetail to STDERR.
*
* @param string $message Message of the fail.
* @return void
* @access public
*/
function paintFail($message) {
parent::paintFail($message);
$message .= $this->_getBreadcrumb();
fwrite(STDERR, 'FAIL' . $this->separator . $message);
}
/**
* Paint PHP errors to STDERR.
*
* @param string $message Message of the Error
* @return void
* @access public
*/
function paintError($message) {
parent::paintError($message);
$message .= $this->_getBreadcrumb();
fwrite(STDERR, 'ERROR' . $this->separator . $message);
}
/**
* Paint exception faildetail to STDERR.
*
* @param string $message Message of the Error
* @return void
* @access public
*/
function paintException($exception) {
parent::paintException($exception);
$message .= sprintf('Unexpected exception of type [%s] with message [%s] in [%s] line [%s]',
get_class($exception),
$exception->getMessage(),
$exception->getFile(),
$exception->getLine()
);
$message .= $this->_getBreadcrumb();
fwrite(STDERR, 'EXCEPTION' . $this->separator . $message);
}
/**
* Get the breadcrumb trail for the current test method/case
*
* @return string The string for the breadcrumb
*/
function _getBreadcrumb() {
$breadcrumb = $this->getTestList();
array_shift($breadcrumb);
$out = "\n\tin " . implode("\n\tin ", array_reverse($breadcrumb));
$out .= "\n\n";
return $out;
}
/**
* Paint a test skip message
*
* @param string $message The message of the skip
* @return void
*/
function paintSkip($message) {
parent::paintSkip($message);
fwrite(STDOUT, 'SKIP' . $this->separator . $message . "\n\n");
}
/**
* Paint a footer with test case name, timestamp, counts of fails and exceptions.
*/
function paintFooter($test_name) {
$buffer = $this->getTestCaseProgress() . '/' . $this->getTestCaseCount() . ' test cases complete: ';
if (0 < ($this->getFailCount() + $this->getExceptionCount())) {
$buffer .= $this->getPassCount() . " passes";
if (0 < $this->getFailCount()) {
$buffer .= ", " . $this->getFailCount() . " fails";
}
if (0 < $this->getExceptionCount()) {
$buffer .= ", " . $this->getExceptionCount() . " exceptions";
}
$buffer .= ".\n";
$buffer .= $this->_timeStats();
fwrite(STDOUT, $buffer);
} else {
fwrite(STDOUT, $buffer . $this->getPassCount() . " passes.\n" . $this->_timeStats());
}
if (
isset($this->params['codeCoverage']) &&
$this->params['codeCoverage'] &&
class_exists('CodeCoverageManager')
) {
CodeCoverageManager::report();
}
}
/**
* Get the time and memory stats for this test case/group
*
* @return string String content to display
* @access protected
*/
function _timeStats() {
$out = 'Time taken by tests (in seconds): ' . $this->_timeDuration . "\n";
if (function_exists('memory_get_peak_usage')) {
$out .= 'Peak memory use: (in bytes): ' . number_format(memory_get_peak_usage()) . "\n";
}
return $out;
}
}
?>

View file

@ -1,6 +1,6 @@
<?php
/**
* Short description for file.
* CakeHtmlReporter
*
* PHP versions 4 and 5
*
@ -11,100 +11,133 @@
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
* @link http://cakephp.org
* @package cake
* @subpackage cake.cake.tests.libs
* @subpackage cake.tests.libs.reporter
* @since CakePHP(tm) v 1.2.0.4433
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
include_once dirname(__FILE__) . DS . 'cake_base_reporter.php';
/**
* CakeHtmlReporter Reports Results of TestSuites and Test Cases
* in an HTML format / context.
*
* @package cake
* @subpackage cake.cake.tests.lib
* @subpackage cake.tests.lib
*/
class CakeHtmlReporter extends SimpleReporter {
var $_character_set;
var $_show_passes = false;
var $_timeStart = 0;
var $_timeEnd = 0;
var $_timeDuration = 0;
/**
* Does nothing yet. The first output will
* be sent on the first test start. For use
* by a web browser.
*
* @access public
*/
function CakeHtmlReporter($character_set = 'ISO-8859-1') {
if (isset($_GET['show_passes']) && $_GET['show_passes']) {
$this->_show_passes = true;
}
$this->SimpleReporter();
$this->_character_set = $character_set;
}
/**
* Signals / Paints the beginning of a TestSuite executing.
* Starts the timer for the TestSuite execution time.
*
* @param
* @return void
*/
function paintGroupStart($test_name, $size) {
if (empty($this->_timeStart)) {
$this->_timeStart = $this->_getTime();
}
parent::paintGroupStart($test_name, $size);
}
/**
* Signals/Paints the end of a TestSuite. All test cases have run
* and timers are stopped.
*
* @return void
*/
function paintGroupEnd($test_name) {
$this->_timeEnd = $this->_getTime();
$this->_timeDuration = $this->_timeEnd - $this->_timeStart;
parent::paintGroupEnd($test_name);
}
/**
* Get the current time in microseconds. Similar to getMicrotime in basics.php
* but in a separate function to reduce dependancies.
*
* @return float Time in microseconds
*/
function _getTime() {
list($usec, $sec) = explode(' ', microtime());
return ((float)$sec + (float)$usec);
}
class CakeHtmlReporter extends CakeBaseReporter {
/**
* Paints the top of the web page setting the
* title to the name of the starting test.
*
* @param string $test_name Name class of test.
* @return void
* @access public
*/
function paintHeader($testName) {
$this->sendNoCacheHeaders();
$this->paintDocumentStart();
$this->paintTestMenu();
echo "<h2>$testName</h2>\n";
echo "<ul class='tests'>\n";
}
/**
* Paints the document start content contained in header.php
*
* @return void
*/
function paintDocumentStart() {
ob_start();
$baseDir = $this->params['baseDir'];
include CAKE_TESTS_LIB . 'templates' . DS . 'header.php';
}
/**
* Paints the menu on the left side of the test suite interface.
* Contains all of the various plugin, core, and app buttons.
*
* @return void
*/
function paintTestMenu() {
$groups = $this->baseUrl() . '?show=groups';
$cases = $this->baseUrl() . '?show=cases';
$plugins = App::objects('plugin');
include CAKE_TESTS_LIB . 'templates' . DS . 'menu.php';
}
/**
* Retrieves and paints the list of tests cases in an HTML format.
*
* @return void
*/
function testCaseList() {
$testCases = parent::testCaseList();
$app = $this->params['app'];
$plugin = $this->params['plugin'];
$buffer = "<h3>Core Test Cases:</h3>\n<ul>";
$urlExtra = null;
if ($app) {
$buffer = "<h3>App Test Cases:</h3>\n<ul>";
$urlExtra = '&app=true';
} elseif ($plugin) {
$buffer = "<h3>" . Inflector::humanize($plugin) . " Test Cases:</h3>\n<ul>";
$urlExtra = '&plugin=' . $plugin;
}
if (1 > count($testCases)) {
$buffer .= "<strong>EMPTY</strong>";
}
foreach ($testCases as $testCaseFile => $testCase) {
$title = explode(strpos($testCase, '\\') ? '\\' : '/', str_replace('.test.php', '', $testCase));
$title[count($title) - 1] = Inflector::camelize($title[count($title) - 1]);
$title = implode(' / ', $title);
$buffer .= "<li><a href='" . $this->baseUrl() . "?case=" . urlencode($testCase) . $urlExtra ."'>" . $title . "</a></li>\n";
}
$buffer .= "</ul>\n";
echo $buffer;
}
/**
* Retrieves and paints the list of group tests in an HTML format.
*
* @return void
*/
function groupTestList() {
$groupTests = parent::groupTestList();
$app = $this->params['app'];
$plugin = $this->params['plugin'];
$buffer = "<h3>Core Test Groups:</h3>\n<ul>";
$urlExtra = null;
if ($app) {
$buffer = "<h3>App Test Groups:</h3>\n<ul>";
$urlExtra = '&app=true';
} else if ($plugin) {
$buffer = "<h3>" . Inflector::humanize($plugin) . " Test Groups:</h3>\n<ul>";
$urlExtra = '&plugin=' . $plugin;
}
$buffer .= "<li><a href='" . $this->baseURL() . "?group=all$urlExtra'>All tests</a></li>\n";
foreach ($groupTests as $groupTest) {
$buffer .= "<li><a href='" . $this->baseURL() . "?group={$groupTest}" . "{$urlExtra}'>" . $groupTest . "</a></li>\n";
}
$buffer .= "</ul>\n";
echo $buffer;
}
/**
* Send the headers necessary to ensure the page is
* reloaded on every request. Otherwise you could be
* scratching your head over out of date test data.
*
* @return void
* @access public
* @static
*/
function sendNoCacheHeaders() {
if (!headers_sent()) {
@ -121,6 +154,7 @@ class CakeHtmlReporter extends SimpleReporter {
* the passes and failures.
*
* @param string $test_name Name class of test.
* @return void
* @access public
*/
function paintFooter($test_name) {
@ -140,7 +174,74 @@ class CakeHtmlReporter extends SimpleReporter {
if (function_exists('memory_get_peak_usage')) {
echo '<p><strong>Peak memory use: (in bytes):</strong> ' . number_format(memory_get_peak_usage()) . '</p>';
}
echo $this->_paintLinks();
echo '</div>';
if (
isset($this->params['codeCoverage']) &&
$this->params['codeCoverage'] &&
class_exists('CodeCoverageManager')
) {
CodeCoverageManager::report();
}
$this->paintDocumentEnd();
}
/**
* Renders the links that for accessing things in the test suite.
*
* @return void
*/
function _paintLinks() {
$show = $query = array();
if (!empty($this->params['group'])) {
$show['show'] = 'groups';
} elseif (!empty($this->params['case'])) {
$show['show'] = 'cases';
}
if (!empty($this->params['app'])) {
$show['app'] = $query['app'] = 'true';
}
if (!empty($this->params['plugin'])) {
$show['plugin'] = $query['plugin'] = $this->params['plugin'];
}
if (!empty($this->params['case'])) {
$query['case'] = $this->params['case'];
} elseif (!empty($this->params['group'])) {
$query['group'] = $this->params['group'];
}
$show = $this->_queryString($show);
$query = $this->_queryString($query);
echo "<p><a href='" . $this->baseUrl() . $show . "'>Run more tests</a> | <a href='" . $this->baseUrl() . $query . "&show_passes=1'>Show Passes</a> | \n";
echo " <a href='" . $this->baseUrl() . $query . "&amp;code_coverage=true'>Analyze Code Coverage</a></p>\n";
}
/**
* Convert an array of parameters into a query string url
*
* @param array $url Url hash to be converted
* @return string Converted url query string
*/
function _queryString($url) {
$out = '?';
$params = array();
foreach ($url as $key => $value) {
$params[] = "$key=$value";
}
$out .= implode('&amp;', $params);
return $out;
}
/**
* Paints the end of the document html.
*
* @return void
*/
function paintDocumentEnd() {
$baseDir = $this->params['baseDir'];
include CAKE_TESTS_LIB . 'templates' . DS . 'footer.php';
ob_end_flush();
}
/**
@ -150,6 +251,7 @@ class CakeHtmlReporter extends SimpleReporter {
*
* @param string $message Failure message displayed in
* the context of the other tests.
* @return void
* @access public
*/
function paintFail($message) {
@ -157,7 +259,7 @@ class CakeHtmlReporter extends SimpleReporter {
echo "<li class='fail'>\n";
echo "<span>Failed</span>";
echo "<div class='msg'>" . $this->_htmlEntities($message) . "</div>\n";
$breadcrumb = Set::filter($this->getTestList());
$breadcrumb = $this->getTestList();
array_shift($breadcrumb);
echo "<div>" . implode(" -&gt; ", $breadcrumb) . "</div>\n";
echo "</li>\n";
@ -169,15 +271,16 @@ class CakeHtmlReporter extends SimpleReporter {
* top level test.
*
* @param string $message Pass message displayed in the context of the other tests.
* @return void
* @access public
*/
function paintPass($message) {
parent::paintPass($message);
if ($this->_show_passes) {
if (isset($this->params['show_passes']) && $this->params['show_passes']) {
echo "<li class='pass'>\n";
echo "<span>Passed</span> ";
$breadcrumb = Set::filter($this->getTestList());
$breadcrumb = $this->getTestList();
array_shift($breadcrumb);
echo implode(" -&gt; ", $breadcrumb);
echo "<br />" . $this->_htmlEntities($message) . "\n";
@ -189,6 +292,7 @@ class CakeHtmlReporter extends SimpleReporter {
* Paints a PHP error.
*
* @param string $message Message is ignored.
* @return void
* @access public
*/
function paintError($message) {
@ -196,7 +300,7 @@ class CakeHtmlReporter extends SimpleReporter {
echo "<li class='error'>\n";
echo "<span>Error</span>";
echo "<div class='msg'>" . $this->_htmlEntities($message) . "</div>\n";
$breadcrumb = Set::filter($this->getTestList());
$breadcrumb = $this->getTestList();
array_shift($breadcrumb);
echo "<div>" . implode(" -&gt; ", $breadcrumb) . "</div>\n";
echo "</li>\n";
@ -206,6 +310,7 @@ class CakeHtmlReporter extends SimpleReporter {
* Paints a PHP exception.
*
* @param Exception $exception Exception to display.
* @return void
* @access public
*/
function paintException($exception) {
@ -217,7 +322,7 @@ class CakeHtmlReporter extends SimpleReporter {
'] in ['. $exception->getFile() .
' line ' . $exception->getLine() . ']';
echo "<div class='msg'>" . $this->_htmlEntities($message) . "</div>\n";
$breadcrumb = Set::filter($this->getTestList());
$breadcrumb = $this->getTestList();
array_shift($breadcrumb);
echo "<div>" . implode(" -&gt; ", $breadcrumb) . "</div>\n";
echo "</li>\n";
@ -226,7 +331,8 @@ class CakeHtmlReporter extends SimpleReporter {
/**
* Prints the message for skipping tests.
*
* @param string $message Text of skip condition.
* @param string $message Text of skip condition.
* @return void
* @access public
*/
function paintSkip($message) {
@ -241,6 +347,7 @@ class CakeHtmlReporter extends SimpleReporter {
* Paints formatted text such as dumped variables.
*
* @param string $message Text to show.
* @return void
* @access public
*/
function paintFormattedMessage($message) {
@ -255,7 +362,7 @@ class CakeHtmlReporter extends SimpleReporter {
* @access protected
*/
function _htmlEntities($message) {
return htmlentities($message, ENT_COMPAT, $this->_character_set);
return htmlentities($message, ENT_COMPAT, $this->_characterSet);
}
}
?>

View file

@ -0,0 +1,199 @@
<?php
/**
* CakeTextReporter contains reporting features used for plain text based output
*
* PHP versions 4 and 5
*
* CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
* Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The Open Group Test Suite License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org
* @package cake
* @subpackage cake.tests.libs.reporter
* @since CakePHP(tm) v 1.3
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
include_once dirname(__FILE__) . DS . 'cake_base_reporter.php';
/**
* CakeTextReporter contains reporting features used for plain text based output
*
* @package cake
* @subpackage cake.tests.lib
*/
class CakeTextReporter extends CakeBaseReporter {
/**
* Sets the text/plain header if the test is not a CLI test.
*
* @return void
*/
function paintDocumentStart() {
if (!SimpleReporter::inCli()) {
header('Content-type: text/plain');
}
}
/**
* Paints the end of the test with a summary of
* the passes and failures.
*
* @param string $test_name Name class of test.
* @return void
* @access public
*/
function paintFooter($test_name) {
if ($this->getFailCount() + $this->getExceptionCount() == 0) {
echo "OK\n";
} else {
echo "FAILURES!!!\n";
}
echo "Test cases run: " . $this->getTestCaseProgress() .
"/" . $this->getTestCaseCount() .
", Passes: " . $this->getPassCount() .
", Failures: " . $this->getFailCount() .
", Exceptions: " . $this->getExceptionCount() . "\n";
echo 'Time taken by tests (in seconds): ' . $this->_timeDuration . "\n";
if (function_exists('memory_get_peak_usage')) {
echo 'Peak memory use: (in bytes): ' . number_format(memory_get_peak_usage()) . "\n";
}
if (
isset($this->params['codeCoverage']) &&
$this->params['codeCoverage'] &&
class_exists('CodeCoverageManager')
) {
CodeCoverageManager::report();
}
}
/**
* Paints the title only.
*
* @param string $test_name Name class of test.
* @return void
* @access public
*/
function paintHeader($test_name) {
$this->paintDocumentStart();
echo "$test_name\n";
flush();
}
/**
* Paints the test failure as a stack trace.
*
* @param string $message Failure message displayed in
* the context of the other tests.
* @return void
* @access public
*/
function paintFail($message) {
parent::paintFail($message);
echo $this->getFailCount() . ") $message\n";
$breadcrumb = $this->getTestList();
array_shift($breadcrumb);
echo "\tin " . implode("\n\tin ", array_reverse($breadcrumb));
echo "\n";
}
/**
* Paints a PHP error.
*
* @param string $message Message to be shown.
* @return void
* @access public
*/
function paintError($message) {
parent::paintError($message);
echo "Exception " . $this->getExceptionCount() . "!\n$message\n";
$breadcrumb = $this->getTestList();
array_shift($breadcrumb);
echo "\tin " . implode("\n\tin ", array_reverse($breadcrumb));
echo "\n";
}
/**
* Paints a PHP exception.
*
* @param Exception $exception Exception to describe.
* @return void
* @access public
*/
function paintException($exception) {
parent::paintException($exception);
$message = 'Unexpected exception of type [' . get_class($exception) .
'] with message ['. $exception->getMessage() .
'] in ['. $exception->getFile() .
' line ' . $exception->getLine() . ']';
echo "Exception " . $this->getExceptionCount() . "!\n$message\n";
$breadcrumb = $this->getTestList();
array_shift($breadcrumb);
echo "\tin " . implode("\n\tin ", array_reverse($breadcrumb));
echo "\n";
}
/**
* Prints the message for skipping tests.
*
* @param string $message Text of skip condition.
* @return void
* @access public
*/
function paintSkip($message) {
parent::paintSkip($message);
echo "Skip: $message\n";
}
/**
* Paints formatted text such as dumped variables.
*
* @param string $message Text to show.
* @return void
* @access public
*/
function paintFormattedMessage($message) {
echo "$message\n";
flush();
}
/**
* Generate a test case list in plain text.
* Creates as series of url's for tests that can be run.
* One case per line.
*
* @return void
*/
function testCaseList() {
$testCases = parent::testCaseList();
$app = $this->params['app'];
$plugin = $this->params['plugin'];
$buffer = "Core Test Cases:\n";
$urlExtra = '';
if ($app) {
$buffer = "App Test Cases:\n";
$urlExtra = '&app=true';
} elseif ($plugin) {
$buffer = Inflector::humanize($plugin) . " Test Cases:\n";
$urlExtra = '&plugin=' . $plugin;
}
if (1 > count($testCases)) {
$buffer .= "EMPTY";
echo $buffer;
}
foreach ($testCases as $testCaseFile => $testCase) {
$buffer .= $_SERVER['SERVER_NAME'] . $this->baseUrl() ."?case=" . $testCase . "&output=text"."\n";
}
$buffer .= "\n";
echo $buffer;
}
}
?>

View file

@ -22,7 +22,7 @@
<div id="footer">
<!--PLEASE USE ONE OF THE POWERED BY CAKEPHP LOGO-->
<a href="http://www.cakephp.org/" target="_blank">
<img src="<?php echo $baseUrl; ?>img/cake.power.gif" alt="CakePHP(tm) :: Rapid Development Framework" /></a></p>
<img src="<?php echo $baseDir; ?>img/cake.power.gif" alt="CakePHP(tm) :: Rapid Development Framework" /></a></p>
</div>
<?php
App::import('Core', 'View');

View file

@ -21,7 +21,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv='content-Type' content='text/html; <?php echo $characterSet; ?>' />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>CakePHP Test Suite 1.3</title>
<style type="text/css">
h3 {font-size: 170%; padding-top: 1em}
@ -114,7 +114,7 @@
div.code-coverage-results span.result-ok { color: #fa0; }
div.code-coverage-results span.result-good { color: #0a0; }
</style>
<link rel="stylesheet" type="text/css" href="<?php echo $baseUrl; ?>css/cake.generic.css" />
<link rel="stylesheet" type="text/css" href="<?php echo $baseDir; ?>css/cake.generic.css" />
</head>
<body>
<div id="container">

View file

@ -21,7 +21,7 @@
<div class="test-menu">
<ul>
<li>
<span style="font-size: 18px">App</span>
<span style="font-size: 18px">App</span>
<ul>
<li><a href='<?php echo $groups;?>&amp;app=true'>Test Groups</a></li>
<li><a href='<?php echo $cases;?>&amp;app=true'>Test Cases</a></li>
@ -31,7 +31,7 @@
if (!empty($plugins)):
?>
<li style="padding-top: 10px">
<span style="font-size: 18px">Plugins</span>
<span style="font-size: 18px">Plugins</span>
<?php foreach($plugins as $plugin):
$pluginPath = Inflector::underscore($plugin);
?>

View file

@ -1,6 +1,6 @@
<?php
/**
* Short description for file.
* Missing SimpleTest error page.
*
* PHP versions 4 and 5
*
@ -18,6 +18,7 @@
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
?>
<?php include dirname(__FILE__) . DS . 'header.php'; ?>
<div id="content">
<h2>SimpleTest is not installed</h2>
<p>You must install SimpleTest to use the CakePHP(tm) Test Suite.</p>
@ -27,4 +28,5 @@
<li><?php echo APP_DIR . DS; ?>vendors</li>
</ul>
<p><a href="http://simpletest.org/en/download.html" target="_blank">Download SimpleTest</a></p>
</div>
</div>
<?php include dirname(__FILE__) . DS . 'footer.php'; ?>

View file

@ -1,6 +1,6 @@
<?php
/**
* Short description for file.
* Xdebug error page
*
* PHP versions 4 and 5
*
@ -18,7 +18,10 @@
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
?>
<div id="content">
<h2>Xdebug is not installed</h2>
<p>You must install Xdebug to use the CakePHP(tm) Code Coverage Analyzation.</p>
<p><a href="http://www.xdebug.org/docs/install" target="_blank">Learn How To Install Xdebug</a></p>
<?php include dirname(__FILE__) . DS . 'header.php'; ?>
<div id="content">
<h2>Xdebug is not installed</h2>
<p>You must install Xdebug to use the CakePHP(tm) Code Coverage Analyzation.</p>
<p><a href="http://www.xdebug.org/docs/install" target="_blank">Learn How To Install Xdebug</a></p>
</div>
<?php include dirname(__FILE__) . DS . 'footer.php'; ?>

View file

@ -1,6 +1,6 @@
<?php
/**
* Short description for file.
* TestManager for CakePHP Test suite.
*
* PHP versions 4 and 5
*
@ -23,15 +23,39 @@ define('APP_TEST_CASES', TESTS . 'cases');
define('APP_TEST_GROUPS', TESTS . 'groups');
/**
* Short description for class.
* TestManager is the base class that handles loading and initiating the running
* of TestCase and TestSuite classes that the user has selected.
*
* @package cake
* @subpackage cake.cake.tests.lib
*/
class TestManager {
/**
* Extension suffix for test case files.
*
* @var string
*/
var $_testExtension = '.test.php';
/**
* Extension suffix for group test case files.
*
* @var string
*/
var $_groupExtension = '.group.php';
/**
* Is this test an AppTest?
*
* @var boolean
*/
var $appTest = false;
/**
* Is this test a plugin test?
*
* @var mixed boolean false or string name of the plugin being used.
*/
var $pluginTest = false;
/**
@ -69,18 +93,17 @@ class TestManager {
/**
* Runs all tests in the Application depending on the current appTest setting
*
* @param string $reporter
* @return void
* @param Object $reporter Reporter object for the tests being run.
* @param boolean $testing Are tests supposed to be auto run. Set to true to return testcase list.
* @return mixed
* @access public
*/
function runAllTests(&$reporter, $testing = false) {
$manager =& new TestManager();
$testCases =& $manager->_getTestFileList($manager->_getTestsPath());
if ($manager->appTest) {
$testCases =& $this->_getTestFileList($this->_getTestsPath());
if ($this->appTest) {
$test =& new TestSuite('All App Tests');
} else if ($manager->pluginTest) {
$test =& new TestSuite('All ' . Inflector::humanize($manager->pluginTest) . ' Plugin Tests');
} else if ($this->pluginTest) {
$test =& new TestSuite('All ' . Inflector::humanize($this->pluginTest) . ' Plugin Tests');
} else {
$test =& new TestSuite('All Core Tests');
}
@ -99,15 +122,14 @@ class TestManager {
/**
* Runs a specific test case file
*
* @param string $testCaseFile
* @param string $reporter
* @return void
* @param string $testCaseFile Filename of the test to be run.
* @param Object $reporter Reporter instance to attach to the test case.
* @param boolean $testing Set to true if testing, otherwise test case will be run.
* @return mixed Result of test case being run.
* @access public
*/
function runTestCase($testCaseFile, &$reporter, $testing = false) {
$manager =& new TestManager();
$testCaseFileWithPath = $manager->_getTestsPath() . DS . $testCaseFile;
$testCaseFileWithPath = $this->_getTestsPath() . DS . $testCaseFile;
if (!file_exists($testCaseFileWithPath)) {
trigger_error("Test case {$testCaseFile} cannot be found", E_USER_ERROR);
@ -126,14 +148,13 @@ class TestManager {
/**
* Runs a specific group test file
*
* @param string $groupTestName
* @param string $reporter
* @return void
* @param string $groupTestName GroupTest that you want to run.
* @param Object $reporter Reporter instance to use with the group test being run.
* @return mixed Results of group test being run.
* @access public
*/
function runGroupTest($groupTestName, &$reporter) {
$manager =& new TestManager();
$filePath = $manager->_getTestsPath('groups') . DS . strtolower($groupTestName) . $manager->_groupExtension;
$filePath = $this->_getTestsPath('groups') . DS . strtolower($groupTestName) . $this->_groupExtension;
if (!file_exists($filePath)) {
trigger_error("Group test {$groupTestName} cannot be found at {$filePath}", E_USER_ERROR);
@ -141,7 +162,7 @@ class TestManager {
require_once $filePath;
$test =& new TestSuite($groupTestName . ' group test');
foreach ($manager->_getGroupTestClassNames($filePath) as $groupTest) {
foreach ($this->_getGroupTestClassNames($filePath) as $groupTest) {
$testCase = new $groupTest();
$test->addTestCase($testCase);
if (isset($testCase->label)) {
@ -154,10 +175,11 @@ class TestManager {
/**
* Adds all testcases in a given directory to a given GroupTest object
*
* @param string $groupTest
* @param string $directory
* @param object $groupTest Instance of TestSuite/GroupTest that files are to be added to.
* @param string $directory The directory to add tests from.
* @return void
* @access public
* @static
*/
function addTestCasesFromDirectory(&$groupTest, $directory = '.') {
$manager =& new TestManager();
@ -170,18 +192,19 @@ class TestManager {
/**
* Adds a specific test file and thereby all of its test cases and group tests to a given group test file
*
* @param string $groupTest
* @param string $file
* @param object $groupTest Instance of TestSuite/GroupTest that a file should be added to.
* @param string $file The file name, minus the suffix to add.
* @return void
* @access public
* @static
*/
function addTestFile(&$groupTest, $file) {
$manager =& new TestManager();
if (file_exists($file.'.test.php')) {
$file .= '.test.php';
} elseif (file_exists($file.'.group.php')) {
$file .= '.group.php';
if (file_exists($file . $manager->_testExtension)) {
$file .= $manager->_testExtension;
} elseif (file_exists($file . $manager->_groupExtension)) {
$file .= $manager->_groupExtension;
}
$groupTest->addTestFile($file);
}
@ -190,6 +213,7 @@ class TestManager {
* Returns a list of test cases found in the current valid test case path
*
* @access public
* @static
*/
function &getTestCaseList() {
$manager =& new TestManager();
@ -200,7 +224,8 @@ class TestManager {
/**
* Builds the list of test cases from a given directory
*
* @access public
* @param string $directory Directory to get test case list from.
* @access protected
*/
function &_getTestCaseList($directory = '.') {
$fileList =& $this->_getTestFileList($directory);
@ -214,7 +239,8 @@ class TestManager {
/**
* Returns a list of test files from a given directory
*
* @access public
* @param string $directory Directory to get test case files from.
* @access protected
*/
function &_getTestFileList($directory = '.') {
$return = $this->_getRecursiveFileList($directory, array(&$this, '_isTestCaseFile'));
@ -225,6 +251,7 @@ class TestManager {
* Returns a list of group tests found in the current valid test case path
*
* @access public
* @static
*/
function &getGroupTestList() {
$manager =& new TestManager();
@ -235,7 +262,8 @@ class TestManager {
/**
* Returns a list of group test files from a given directory
*
* @access public
* @param string $directory The directory to get group test files from.
* @access protected
*/
function &_getTestGroupFileList($directory = '.') {
$return = $this->_getRecursiveFileList($directory, array(&$this, '_isTestGroupFile'));
@ -245,7 +273,8 @@ class TestManager {
/**
* Returns a list of group test files from a given directory
*
* @access public
* @param string $directory The directory to get group tests from.
* @access protected
*/
function &_getTestGroupList($directory = '.') {
$fileList =& $this->_getTestGroupFileList($directory);
@ -261,7 +290,8 @@ class TestManager {
/**
* Returns a list of class names from a group test file
*
* @access public
* @param string $groupTestFile The groupTest file to scan for TestSuite classnames.
* @access protected
*/
function &_getGroupTestClassNames($groupTestFile) {
$file = implode("\n", file($groupTestFile));
@ -278,7 +308,9 @@ class TestManager {
* Gets a recursive list of files from a given directory and matches then against
* a given fileTestFunction, like isTestCaseFile()
*
* @access public
* @param string $directory The directory to scan for files.
* @param mixed $fileTestFunction
* @access protected
*/
function &_getRecursiveFileList($directory = '.', $fileTestFunction) {
$fileList = array();
@ -303,8 +335,8 @@ class TestManager {
* Tests if a file has the correct test case extension
*
* @param string $file
* @return void
* @access public
* @return boolean Whether $file is a test case.
* @access protected
*/
function _isTestCaseFile($file) {
return $this->_hasExpectedExtension($file, $this->_testExtension);
@ -314,8 +346,8 @@ class TestManager {
* Tests if a file has the correct group test extension
*
* @param string $file
* @return void
* @access public
* @return boolean Whether $file is a group
* @access protected
*/
function _isTestGroupFile($file) {
return $this->_hasExpectedExtension($file, $this->_groupExtension);
@ -327,7 +359,7 @@ class TestManager {
* @param string $file
* @param string $extension
* @return void
* @access public
* @access protected
*/
function _hasExpectedExtension($file, $extension) {
return $extension == strtolower(substr($file, (0 - strlen($extension))));
@ -336,9 +368,9 @@ class TestManager {
/**
* Returns the given path to the test files depending on a given type of tests (cases, group, ..)
*
* @param string $type
* @return void
* @access public
* @param string $type either 'cases' or 'groups'
* @return string The path tests are located on
* @access protected
*/
function _getTestsPath($type = 'cases') {
if (!empty($this->appTest)) {
@ -365,453 +397,18 @@ class TestManager {
}
/**
* undocumented function
* Get the extension for either 'group' or 'test' types.
*
* @param string $type
* @return void
* @param string $type Type of test to get, either 'test' or 'group'
* @return string Extension suffix for test.
* @access public
*/
function getExtension($type = 'test') {
$manager =& new TestManager();
if ($type == 'test') {
return $manager->_testExtension;
if ($type == 'test' || $type == 'case') {
return $this->_testExtension;
}
return $manager->_groupExtension;
return $this->_groupExtension;
}
}
/**
* The CliTestManager ensures that the list of available files are printed in the correct cli format
*
* @package cake
* @subpackage cake.cake.tests.lib
*/
class CliTestManager extends TestManager {
/**
* Prints the list of group tests in a cli friendly format
*
* @access public
*/
function &getGroupTestList() {
$manager =& new CliTestManager();
$groupTests =& $manager->_getTestGroupList($manager->_getTestsPath('groups'));
$buffer = "Available Group Test:\n";
foreach ($groupTests as $groupTest) {
$buffer .= " " . $groupTest . "\n";
}
return $buffer . "\n";
}
/**
* Prints the list of test cases in a cli friendly format
*
* @access public
*/
function &getTestCaseList() {
$manager =& new CliTestManager();
$testCases =& $manager->_getTestCaseList($manager->_getTestsPath());
$buffer = "Available Test Cases:\n";
foreach ($testCases as $testCaseFile => $testCase) {
$buffer .= " " . $testCaseFile . "\n";
}
return $buffer . "\n";
}
}
/**
* The TextTestManager ensures that the list of available tests is printed as a list of urls in a text-friendly format
*
* @package cake
* @subpackage cake.cake.tests.lib
*/
class TextTestManager extends TestManager {
var $_url;
/**
* Constructor
*
* @return void
* @access public
*/
function TextTestManager() {
parent::TestManager();
$this->_url = $_SERVER['PHP_SELF'];
}
/**
* Returns the base url
*
* @return void
* @access public
*/
function getBaseURL() {
return $this->_url;
}
/**
* Returns a list of available group tests in a text-friendly format
*
* @access public
*/
function &getGroupTestList() {
$manager =& new TextTestManager();
$groupTests =& $manager->_getTestGroupList($manager->_getTestsPath('groups'));
$buffer = "Core Test Groups:\n";
$urlExtra = '';
if ($manager->appTest) {
$buffer = "App Test Groups:\n";
$urlExtra = '&app=true';
} else if ($manager->pluginTest) {
$buffer = Inflector::humanize($manager->pluginTest) . " Test Groups:\n";
$urlExtra = '&plugin=' . $manager->pluginTest;
}
$buffer .= "All tests\n" . $_SERVER['SERVER_NAME'] . $manager->getBaseURL() . "?group=all&output=txt{$urlExtra}\n";
foreach ((array)$groupTests as $groupTest) {
$buffer .= $_SERVER['SERVER_NAME']. $manager->getBaseURL()."?group=" . $groupTest . "&output=txt{$urlExtra}"."\n";
}
return $buffer;
}
/**
* Returns a list of available test cases in a text-friendly format
*
* @access public
*/
function &getTestCaseList() {
$manager =& new TextTestManager();
$testCases =& $manager->_getTestCaseList($manager->_getTestsPath());
$buffer = "Core Test Cases:\n";
$urlExtra = '';
if ($manager->appTest) {
$buffer = "App Test Cases:\n";
$urlExtra = '&app=true';
} else if ($manager->pluginTest) {
$buffer = Inflector::humanize($manager->pluginTest) . " Test Cases:\n";
$urlExtra = '&plugin=' . $manager->pluginTest;
}
if (1 > count($testCases)) {
$buffer .= "EMPTY";
return $buffer;
}
foreach ($testCases as $testCaseFile => $testCase) {
$buffer .= $_SERVER['SERVER_NAME']. $manager->getBaseURL()."?case=" . $testCase . "&output=txt"."\n";
}
$buffer .= "\n";
return $buffer;
}
}
/**
* The HtmlTestManager provides the foundation for the web-based CakePHP testsuite.
* It prints the different lists of tests and provides the interface for CodeCoverage, etc.
*
* @package cake
* @subpackage cake.cake.tests.lib
*/
class HtmlTestManager extends TestManager {
var $_url;
/**
* Constructor
*
* @return void
* @access public
*/
function HtmlTestManager() {
parent::TestManager();
$this->_url = $_SERVER['PHP_SELF'];
}
/**
* Returns the current base url
*
* @return void
* @access public
*/
function getBaseURL() {
return $this->_url;
}
/**
* Prints the links to the available group tests
*
* @access public
*/
function &getGroupTestList() {
$urlExtra = '';
$manager =& new HtmlTestManager();
$groupTests =& $manager->_getTestGroupList($manager->_getTestsPath('groups'));
$buffer = "<h3>Core Test Groups:</h3>\n<ul>";
$urlExtra = null;
if ($manager->appTest) {
$buffer = "<h3>App Test Groups:</h3>\n<ul>";
$urlExtra = '&app=true';
} else if ($manager->pluginTest) {
$buffer = "<h3>" . Inflector::humanize($manager->pluginTest) . " Test Groups:</h3>\n<ul>";
$urlExtra = '&plugin=' . $manager->pluginTest;
}
$buffer .= "<li><a href='" . $manager->getBaseURL() . "?group=all$urlExtra'>All tests</a></li>\n";
foreach ($groupTests as $groupTest) {
$buffer .= "<li><a href='" . $manager->getBaseURL() . "?group={$groupTest}" . "{$urlExtra}'>" . $groupTest . "</a></li>\n";
}
$buffer .= "</ul>\n";
return $buffer;
}
/**
* Prints the links to the available test cases
*
* @access public
*/
function &getTestCaseList() {
$urlExtra = '';
$manager =& new HtmlTestManager();
$testCases =& $manager->_getTestCaseList($manager->_getTestsPath());
$buffer = "<h3>Core Test Cases:</h3>\n<ul>";
$urlExtra = null;
if ($manager->appTest) {
$buffer = "<h3>App Test Cases:</h3>\n<ul>";
$urlExtra = '&app=true';
} else if ($manager->pluginTest) {
$buffer = "<h3>" . Inflector::humanize($manager->pluginTest) . " Test Cases:</h3>\n<ul>";
$urlExtra = '&plugin=' . $manager->pluginTest;
}
if (1 > count($testCases)) {
$buffer .= "<strong>EMPTY</strong>";
return $buffer;
}
foreach ($testCases as $testCaseFile => $testCase) {
$title = explode(strpos($testCase, '\\') ? '\\' : '/', str_replace('.test.php', '', $testCase));
$title[count($title) - 1] = Inflector::camelize($title[count($title) - 1]);
$title = implode(' / ', $title);
$buffer .= "<li><a href='" . $manager->getBaseURL() . "?case=" . urlencode($testCase) . $urlExtra ."'>" . $title . "</a></li>\n";
}
$buffer .= "</ul>\n";
return $buffer;
}
}
if (function_exists('caketestsgetreporter')) {
echo "You need a new test.php. \n";
echo "Try this one: " . dirname(CONSOLE_LIBS) . "templates" . DS . "skel" . DS . "webroot" . DS . "test.php";
exit();
} else {
/**
* Returns an object of the currently needed reporter
*
* @access public
*/
function &CakeTestsGetReporter() {
static $Reporter = NULL;
if (!$Reporter) {
switch (CAKE_TEST_OUTPUT) {
case CAKE_TEST_OUTPUT_HTML:
require_once CAKE_TESTS_LIB . 'cake_reporter.php';
$Reporter =& new CakeHtmlReporter();
break;
default:
require_once CAKE_TESTS_LIB . 'cake_text_reporter.php';
$Reporter =& new CakeTextReporter();
break;
}
}
return $Reporter;
}
/**
* Provides the "Run More" links in the testsuite interface
*
* @return void
* @access public
*/
function CakePHPTestRunMore() {
switch (CAKE_TEST_OUTPUT) {
case CAKE_TEST_OUTPUT_HTML:
if (isset($_GET['group'])) {
if (isset($_GET['app'])) {
$show = '?show=groups&amp;app=true';
} else if (isset($_GET['plugin'])) {
$show = '?show=groups&amp;plugin=' . $_GET['plugin'];
} else {
$show = '?show=groups';
}
$query = '?group='.$_GET['group'];
if (isset($_GET['app'])) {
$query .= '&amp;app=true';
} elseif (isset($_GET['plugin'])) {
$query .= '&amp;plugin=' . $_GET['plugin'];
}
}
if (isset($_GET['case'])) {
if (isset($_GET['app'])) {
$show = '?show=cases&amp;app=true';
} else if (isset($_GET['plugin'])) {
$show = '?show=cases&amp;plugin=' . $_GET['plugin'];
} else {
$show = '?show=cases';
}
$query = '?case='.$_GET['case'];
if (isset($_GET['app'])) {
$query .= '&amp;app=true';
} elseif (isset($_GET['plugin'])) {
$query .= '&amp;plugin=' . $_GET['plugin'];
}
}
ob_start();
echo "<p><a href='" . RUN_TEST_LINK . $show . "'>Run more tests</a> | <a href='" . RUN_TEST_LINK . $query . "&show_passes=1'>Show Passes</a> | \n";
break;
}
}
/**
* Provides the links to analyzing code coverage
*
* @return void
* @access public
*/
function CakePHPTestAnalyzeCodeCoverage() {
switch (CAKE_TEST_OUTPUT) {
case CAKE_TEST_OUTPUT_HTML:
if (isset($_GET['case'])) {
$query = '?case='.$_GET['case'];
if (isset($_GET['app'])) {
$query .= '&amp;app=true';
} elseif (isset($_GET['plugin'])) {
$query .= '&amp;plugin=' . $_GET['plugin'];
}
} else {
$query = '?group='.$_GET['group'];
if (isset($_GET['app'])) {
$query .= '&amp;app=true';
} elseif (isset($_GET['plugin'])) {
$query .= '&amp;plugin=' . $_GET['plugin'];
}
}
$query .= '&amp;code_coverage=true';
ob_start();
echo " <a href='" . RUN_TEST_LINK . $query . "'>Analyze Code Coverage</a></p>\n";
break;
}
}
/**
* Prints a list of test cases
*
* @return void
* @access public
*/
function CakePHPTestCaseList() {
switch (CAKE_TEST_OUTPUT) {
case CAKE_TEST_OUTPUT_HTML:
ob_start();
echo HtmlTestManager::getTestCaseList();
break;
case CAKE_TEST_OUTPUT_TEXT:
default:
echo TextTestManager::getTestCaseList();
break;
}
}
/**
* Prints a list of group tests
*
* @return void
* @access public
*/
function CakePHPTestGroupTestList() {
switch (CAKE_TEST_OUTPUT) {
case CAKE_TEST_OUTPUT_HTML:
echo HtmlTestManager::getGroupTestList();
break;
case CAKE_TEST_OUTPUT_TEXT:
default:
echo TextTestManager::getGroupTestList();
break;
}
}
/**
* Includes the Testsuite Header
*
* @return void
* @access public
*/
function CakePHPTestHeader() {
switch (CAKE_TEST_OUTPUT) {
case CAKE_TEST_OUTPUT_HTML:
ob_start();
if (!class_exists('dispatcher')) {
require CAKE . 'dispatcher.php';
}
$dispatch =& new Dispatcher();
$dispatch->baseUrl();
define('BASE', $dispatch->webroot);
$baseUrl = BASE;
$characterSet = 'charset=utf-8';
include CAKE_TESTS_LIB . 'header.php';
break;
case CAKE_TEST_OUTPUT_TEXT:
default:
header('content-type: text/plain');
break;
}
}
/**
* Provides the left hand navigation for the testsuite
*
* @return void
* @access public
*/
function CakePHPTestSuiteHeader() {
switch (CAKE_TEST_OUTPUT) {
case CAKE_TEST_OUTPUT_HTML:
ob_start();
$groups = $_SERVER['PHP_SELF'].'?show=groups';
$cases = $_SERVER['PHP_SELF'].'?show=cases';
$plugins = App::objects('plugin');
include CAKE_TESTS_LIB . 'content.php';
break;
}
}
/**
* Provides the testsuite footer text
*
* @return void
* @access public
*/
function CakePHPTestSuiteFooter() {
switch ( CAKE_TEST_OUTPUT) {
case CAKE_TEST_OUTPUT_HTML:
ob_start();
$baseUrl = BASE;
include CAKE_TESTS_LIB . 'footer.php';
break;
}
}
}
?>