testsuite.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: testsuite_8php-source.html 580 2008-07-01 14:45:49Z gwoo $ */
00003 /**
00004  * Test Suite Shell
00005  *
00006  * This Shell allows the running of test suites via the cake command line
00007  *
00008  * PHP versions 4 and 5
00009  *
00010  * CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
00011  * Copyright 2005-2008, Cake Software Foundation, Inc.
00012  *                              1785 E. Sahara Avenue, Suite 490-204
00013  *                              Las Vegas, Nevada 89104
00014  *
00015  *  Licensed under The Open Group Test Suite License
00016  *  Redistributions of files must retain the above copyright notice.
00017  *
00018  * @filesource
00019  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00020  * @link                https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
00021  * @package         cake
00022  * @subpackage      cake.cake.console.libs
00023  * @since           CakePHP(tm) v 1.2.0.4433
00024  * @version         $Revision: 580 $
00025  * @modifiedby      $LastChangedBy: gwoo $
00026  * @lastmodified    $Date: 2008-07-01 09:45:49 -0500 (Tue, 01 Jul 2008) $
00027  * @license         http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
00028  */
00029 class TestSuiteShell extends Shell {
00030 /**
00031  * The test category, "app", "core" or the name of a plugin
00032  *
00033  * @var string
00034  * @access public
00035  */
00036     var $category = '';
00037 /**
00038  * "group", "case" or "all"
00039  *
00040  * @var string
00041  * @access public
00042  */
00043     var $type = '';
00044 /**
00045  * Path to the test case/group file
00046  *
00047  * @var string
00048  * @access public
00049  */
00050     var $file = '';
00051 /**
00052  * Storage for plugins that have tests
00053  *
00054  * @var string
00055  * @access public
00056  */
00057     var $plugins = array();
00058 /**
00059  * Convenience variable to avoid duplicated code
00060  *
00061  * @var string
00062  * @access public
00063  */
00064     var $isPluginTest = false;
00065 /**
00066  * Stores if the user wishes to get a code coverage analysis report
00067  *
00068  * @var string
00069  * @access public
00070  */
00071     var $doCoverage = false;
00072 /**
00073  * The headline for the test output
00074  *
00075  * @var string
00076  * @access public
00077  */
00078     var $headline = 'CakePHP Test Shell';
00079 /**
00080  * Initialization method installs Simpletest and loads all plugins
00081  *
00082  * @return void
00083  * @access public
00084  */
00085     function initialize() {
00086         $corePath = Configure::corePaths('cake');
00087         if (isset($corePath[0])) {
00088             define('TEST_CAKE_CORE_INCLUDE_PATH', rtrim($corePath[0], DS) . DS);
00089         } else {
00090             define('TEST_CAKE_CORE_INCLUDE_PATH', CAKE_CORE_INCLUDE_PATH);
00091         }
00092 
00093         $this->__installSimpleTest();
00094 
00095         require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_manager.php';
00096         require_once CAKE . 'tests' . DS . 'lib' . DS . 'cli_reporter.php';
00097 
00098         $plugins = Configure::listObjects('plugin');
00099         foreach ($plugins as $p) {
00100             $this->plugins[] = Inflector::underscore($p);
00101         }
00102     }
00103 /**
00104  * Main entry point to this shell
00105  *
00106  * @return void
00107  * @access public
00108  */
00109     function main() {
00110         $this->out($this->headline);
00111         $this->hr();
00112 
00113         if (count($this->args) > 0) {
00114             $this->category = $this->args[0];
00115 
00116             if (!in_array($this->category, array('app', 'core'))) {
00117                 $this->isPluginTest = true;
00118             }
00119 
00120             if (isset($this->args[1])) {
00121                 $this->type = $this->args[1];
00122             }
00123 
00124             if (isset($this->args[2])) {
00125                 if ($this->args[2] == 'cov') {
00126                     $this->doCoverage = true;
00127                 } else {
00128                     $this->file = Inflector::underscore($this->args[2]);
00129                 }
00130             }
00131 
00132             if (isset($this->args[3]) && $this->args[3] == 'cov') {
00133                 $this->doCoverage = true;
00134             }
00135         } else {
00136             $this->err('Sorry, you did not pass any arguments!');
00137         }
00138 
00139         if ($this->__canRun()) {
00140             $this->out('Running '.$this->category.' '.$this->type.' '.$this->file);
00141 
00142             $exitCode = 0;
00143             if (!$this->__run()) {
00144                 $exitCode = 1;
00145             }
00146             exit($exitCode);
00147         } else {
00148             $this->err('Sorry, the tests could not be found.');
00149             exit(1);
00150         }
00151     }
00152 /**
00153  * Help screen
00154  *
00155  * @return void
00156  * @access public
00157  */
00158     function help() {
00159         $this->out('Usage: ');
00160         $this->out("\tcake testsuite category test_type file");
00161         $this->out("\t\t - category - \"app\", \"core\" or name of a plugin");
00162         $this->out("\t\t - test_type - \"case\", \"group\" or \"all\"");
00163         $this->out("\t\t - test_file - file name with folder prefix and without the (test|group).php suffix");
00164         $this->out('');
00165         $this->out('Examples: ');
00166         $this->out("\t\t cake testsuite app all");
00167         $this->out("\t\t cake testsuite core all");
00168         $this->out('');
00169         $this->out("\t\t cake testsuite app case behaviors/debuggable");
00170         $this->out("\t\t cake testsuite app case models/my_model");
00171         $this->out("\t\t cake testsuite app case controllers/my_controller");
00172         $this->out('');
00173         $this->out("\t\t cake testsuite core case file");
00174         $this->out("\t\t cake testsuite core case router");
00175         $this->out("\t\t cake testsuite core case set");
00176         $this->out('');
00177         $this->out("\t\t cake testsuite app group mygroup");
00178         $this->out("\t\t cake testsuite core group acl");
00179         $this->out("\t\t cake testsuite core group socket");
00180         $this->out('');
00181         $this->out("\t\t cake testsuite bugs case models/bug  // for the plugin 'bugs' and its test case 'bug'");
00182         $this->out("\t\t cake testsuite bugs group bug  // for the plugin bugs and its test group 'bug'");
00183         $this->out("\t\t cake testsuite bugs_me case models/bug  // for the plugin 'bugs_me' and its test case 'bug'");
00184         $this->out("\t\t cake testsuite bugs_me group bug  // for the plugin bugs_me and its test group 'bug'");
00185         $this->out('');
00186         $this->out('Code Coverage Analysis: ');
00187         $this->out("\n\nAppend 'cov' to any of the above in order to enable code coverage analysis");
00188     }
00189 /**
00190  * Checks if the arguments supplied point to a valid test file and thus the shell can be run.
00191  *
00192  * @return bool true if it's a valid test file, false otherwise
00193  * @access private
00194  */
00195     function __canRun() {
00196         $isNeitherAppNorCore = !in_array($this->category, array('app', 'core'));
00197         $isPlugin = in_array(Inflector::underscore($this->category), $this->plugins);
00198 
00199         if ($isNeitherAppNorCore && !$isPlugin) {
00200             $this->err($this->category.' is an invalid test category (either "app", "core" or name of a plugin)');
00201             return false;
00202         }
00203 
00204         $folder = $this->__findFolderByCategory($this->category);
00205         if (!file_exists($folder)) {
00206             $this->err($folder . ' not found');
00207             return false;
00208         }
00209 
00210         if (!in_array($this->type, array('all', 'group', 'case'))) {
00211             $this->err($this->type.' is invalid. Should be case, group or all');
00212             return false;
00213         }
00214 
00215         switch ($this->type) {
00216             case 'all':
00217                 return true;
00218                 break;
00219             case 'group':
00220                 if (file_exists($folder.DS.'groups'.DS.$this->file.'.group.php')) {
00221                     return true;
00222                 }
00223                 break;
00224             case 'case':
00225                 if ($this->category == 'app' && file_exists($folder.DS.'cases'.DS.$this->file.'.test.php')) {
00226                     return true;
00227                 }
00228 
00229                 if ($this->category == 'core' && file_exists($folder.DS.'cases'.DS.'libs'.DS.$this->file.'.test.php')) {
00230                     return true;
00231                 }
00232 
00233                 if ($isPlugin && file_exists($folder.DS.'cases'.DS.$this->file.'.test.php')) {
00234                     return true;
00235                 }
00236                 break;
00237         }
00238 
00239         $this->err($this->category.' '.$this->type.' '.$this->file.' is an invalid test identifier');
00240         return false;
00241     }
00242 /**
00243  * Executes the tests depending on our settings
00244  *
00245  * @return void
00246  * @access private
00247  */
00248     function __run() {
00249         $reporter = new CLIReporter();
00250         $this->__setGetVars();
00251 
00252         if ($this->type == 'all') {
00253             return TestManager::runAllTests($reporter);
00254         }
00255 
00256         if ($this->doCoverage) {
00257             if (!extension_loaded('xdebug')) {
00258                 $this->out('You must install Xdebug to use the CakePHP(tm) Code Coverage Analyzation. Download it from http://www.xdebug.org/docs/install');
00259                 exit(0);
00260             }
00261         }
00262 
00263         if ($this->type == 'group') {
00264             $ucFirstGroup = ucfirst($this->file);
00265 
00266             $path = CORE_TEST_GROUPS;
00267             if ($this->category == 'app') {
00268                 $path = APP_TEST_GROUPS;
00269             } elseif ($this->isPluginTest) {
00270                 $path = APP.'plugins'.DS.$this->category.DS.'tests'.DS.'groups';
00271             }
00272 
00273             if ($this->doCoverage) {
00274                 require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
00275                 CodeCoverageManager::start($ucFirstGroup, $reporter);
00276             }
00277             $result = TestManager::runGroupTest($ucFirstGroup, $reporter);
00278             if ($this->doCoverage) {
00279                 CodeCoverageManager::report();
00280             }
00281             return $result;
00282         }
00283 
00284         $case = 'libs'.DS.$this->file.'.test.php';
00285         if ($this->category == 'app') {
00286             $case = $this->file.'.test.php';
00287         } elseif ($this->isPluginTest) {
00288             $case = $this->file.'.test.php';
00289         }
00290 
00291         if ($this->doCoverage) {
00292             require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
00293             CodeCoverageManager::start($case, $reporter);
00294         }
00295 
00296         $result = TestManager::runTestCase($case, $reporter);
00297         if ($this->doCoverage) {
00298             CodeCoverageManager::report();
00299         }
00300 
00301         return $result;
00302     }
00303 /**
00304  * Finds the correct folder to look for tests for based on the input category
00305  *
00306  * @return string the folder path
00307  * @access private
00308  */
00309     function __findFolderByCategory($category) {
00310         $folder = '';
00311         $paths = array(
00312             'core' => CAKE,
00313             'app'  => APP
00314         );
00315 
00316         if (array_key_exists($category, $paths)) {
00317             $folder = $paths[$category];
00318         } else {
00319             $folder = APP.'plugins'.DS.Inflector::underscore($category).DS;
00320         }
00321         return $folder.'tests';
00322     }
00323 /**
00324  * Sets some get vars needed for TestManager
00325  *
00326  * @return void
00327  * @access private
00328  */
00329     function __setGetVars() {
00330         if (in_array($this->category, $this->plugins)) {
00331             $_GET['plugin'] = $this->category;
00332         } elseif (in_array(Inflector::Humanize($this->category), $this->plugins)) {
00333             $_GET['plugin'] = Inflector::Humanize($this->category);
00334         } elseif ($this->category == 'app') {
00335             $_GET['app'] = true;
00336         }
00337         if ($this->type == 'group') {
00338             $_GET['group'] = true;
00339         }
00340     }
00341 /**
00342  * tries to install simpletest and exits gracefully if it is not there
00343  *
00344  * @return void
00345  * @access private
00346  */
00347     function __installSimpleTest() {
00348         if (!App::import('Vendor', 'simpletest' . DS . 'reporter')) {
00349             $this->err('Sorry, Simpletest could not be found. Download it from http://simpletest.org and install it to your vendors directory.');
00350             exit;
00351         }
00352     }
00353 }
00354 ?>