/cake/console/libs/testsuite.php

https://github.com/hardsshah/bookmarks · PHP · 352 lines · 210 code · 27 blank · 115 comment · 51 complexity · 6d22cb9cf9b709914623832770c3a7c9 MD5 · raw file

  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * Test Suite Shell
  5. *
  6. * This Shell allows the running of test suites via the cake command line
  7. *
  8. * PHP versions 4 and 5
  9. *
  10. * CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
  11. * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
  12. *
  13. * Licensed under The Open Group Test Suite License
  14. * Redistributions of files must retain the above copyright notice.
  15. *
  16. * @filesource
  17. * @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
  18. * @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
  19. * @package cake
  20. * @subpackage cake.cake.console.libs
  21. * @since CakePHP(tm) v 1.2.0.4433
  22. * @version $Revision$
  23. * @modifiedby $LastChangedBy$
  24. * @lastmodified $Date$
  25. * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
  26. */
  27. class TestSuiteShell extends Shell {
  28. /**
  29. * The test category, "app", "core" or the name of a plugin
  30. *
  31. * @var string
  32. * @access public
  33. */
  34. var $category = '';
  35. /**
  36. * "group", "case" or "all"
  37. *
  38. * @var string
  39. * @access public
  40. */
  41. var $type = '';
  42. /**
  43. * Path to the test case/group file
  44. *
  45. * @var string
  46. * @access public
  47. */
  48. var $file = '';
  49. /**
  50. * Storage for plugins that have tests
  51. *
  52. * @var string
  53. * @access public
  54. */
  55. var $plugins = array();
  56. /**
  57. * Convenience variable to avoid duplicated code
  58. *
  59. * @var string
  60. * @access public
  61. */
  62. var $isPluginTest = false;
  63. /**
  64. * Stores if the user wishes to get a code coverage analysis report
  65. *
  66. * @var string
  67. * @access public
  68. */
  69. var $doCoverage = false;
  70. /**
  71. * The headline for the test output
  72. *
  73. * @var string
  74. * @access public
  75. */
  76. var $headline = 'CakePHP Test Shell';
  77. /**
  78. * Initialization method installs Simpletest and loads all plugins
  79. *
  80. * @return void
  81. * @access public
  82. */
  83. function initialize() {
  84. $corePath = Configure::corePaths('cake');
  85. if (isset($corePath[0])) {
  86. define('TEST_CAKE_CORE_INCLUDE_PATH', rtrim($corePath[0], DS) . DS);
  87. } else {
  88. define('TEST_CAKE_CORE_INCLUDE_PATH', CAKE_CORE_INCLUDE_PATH);
  89. }
  90. $this->__installSimpleTest();
  91. require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_manager.php';
  92. require_once CAKE . 'tests' . DS . 'lib' . DS . 'cli_reporter.php';
  93. $plugins = Configure::listObjects('plugin');
  94. foreach ($plugins as $p) {
  95. $this->plugins[] = Inflector::underscore($p);
  96. }
  97. }
  98. /**
  99. * Main entry point to this shell
  100. *
  101. * @return void
  102. * @access public
  103. */
  104. function main() {
  105. $this->out($this->headline);
  106. $this->hr();
  107. if (count($this->args) > 0) {
  108. $this->category = $this->args[0];
  109. if (!in_array($this->category, array('app', 'core'))) {
  110. $this->isPluginTest = true;
  111. }
  112. if (isset($this->args[1])) {
  113. $this->type = $this->args[1];
  114. }
  115. if (isset($this->args[2])) {
  116. if ($this->args[2] == 'cov') {
  117. $this->doCoverage = true;
  118. } else {
  119. $this->file = Inflector::underscore($this->args[2]);
  120. }
  121. }
  122. if (isset($this->args[3]) && $this->args[3] == 'cov') {
  123. $this->doCoverage = true;
  124. }
  125. } else {
  126. $this->err('Sorry, you did not pass any arguments!');
  127. }
  128. if ($this->__canRun()) {
  129. $this->out('Running '.$this->category.' '.$this->type.' '.$this->file);
  130. $exitCode = 0;
  131. if (!$this->__run()) {
  132. $exitCode = 1;
  133. }
  134. exit($exitCode);
  135. } else {
  136. $this->err('Sorry, the tests could not be found.');
  137. exit(1);
  138. }
  139. }
  140. /**
  141. * Help screen
  142. *
  143. * @return void
  144. * @access public
  145. */
  146. function help() {
  147. $this->out('Usage: ');
  148. $this->out("\tcake testsuite category test_type file");
  149. $this->out("\t\t - category - \"app\", \"core\" or name of a plugin");
  150. $this->out("\t\t - test_type - \"case\", \"group\" or \"all\"");
  151. $this->out("\t\t - test_file - file name with folder prefix and without the (test|group).php suffix");
  152. $this->out('');
  153. $this->out('Examples: ');
  154. $this->out("\t\t cake testsuite app all");
  155. $this->out("\t\t cake testsuite core all");
  156. $this->out('');
  157. $this->out("\t\t cake testsuite app case behaviors/debuggable");
  158. $this->out("\t\t cake testsuite app case models/my_model");
  159. $this->out("\t\t cake testsuite app case controllers/my_controller");
  160. $this->out('');
  161. $this->out("\t\t cake testsuite core case file");
  162. $this->out("\t\t cake testsuite core case router");
  163. $this->out("\t\t cake testsuite core case set");
  164. $this->out('');
  165. $this->out("\t\t cake testsuite app group mygroup");
  166. $this->out("\t\t cake testsuite core group acl");
  167. $this->out("\t\t cake testsuite core group socket");
  168. $this->out('');
  169. $this->out("\t\t cake testsuite bugs case models/bug // for the plugin 'bugs' and its test case 'bug'");
  170. $this->out("\t\t cake testsuite bugs group bug // for the plugin bugs and its test group 'bug'");
  171. $this->out("\t\t cake testsuite bugs_me case models/bug // for the plugin 'bugs_me' and its test case 'bug'");
  172. $this->out("\t\t cake testsuite bugs_me group bug // for the plugin bugs_me and its test group 'bug'");
  173. $this->out('');
  174. $this->out('Code Coverage Analysis: ');
  175. $this->out("\n\nAppend 'cov' to any of the above in order to enable code coverage analysis");
  176. }
  177. /**
  178. * Checks if the arguments supplied point to a valid test file and thus the shell can be run.
  179. *
  180. * @return bool true if it's a valid test file, false otherwise
  181. * @access private
  182. */
  183. function __canRun() {
  184. $isNeitherAppNorCore = !in_array($this->category, array('app', 'core'));
  185. $isPlugin = in_array(Inflector::underscore($this->category), $this->plugins);
  186. if ($isNeitherAppNorCore && !$isPlugin) {
  187. $this->err($this->category.' is an invalid test category (either "app", "core" or name of a plugin)');
  188. return false;
  189. }
  190. $folder = $this->__findFolderByCategory($this->category);
  191. if (!file_exists($folder)) {
  192. $this->err($folder . ' not found');
  193. return false;
  194. }
  195. if (!in_array($this->type, array('all', 'group', 'case'))) {
  196. $this->err($this->type.' is invalid. Should be case, group or all');
  197. return false;
  198. }
  199. switch ($this->type) {
  200. case 'all':
  201. return true;
  202. break;
  203. case 'group':
  204. if (file_exists($folder.DS.'groups'.DS.$this->file.'.group.php')) {
  205. return true;
  206. }
  207. break;
  208. case 'case':
  209. if ($this->category == 'app' && file_exists($folder.DS.'cases'.DS.$this->file.'.test.php')) {
  210. return true;
  211. }
  212. if ($this->category == 'core' && file_exists($folder.DS.'cases'.DS.'libs'.DS.$this->file.'.test.php')) {
  213. return true;
  214. }
  215. if ($isPlugin && file_exists($folder.DS.'cases'.DS.$this->file.'.test.php')) {
  216. return true;
  217. }
  218. break;
  219. }
  220. $this->err($this->category.' '.$this->type.' '.$this->file.' is an invalid test identifier');
  221. return false;
  222. }
  223. /**
  224. * Executes the tests depending on our settings
  225. *
  226. * @return void
  227. * @access private
  228. */
  229. function __run() {
  230. $reporter = new CLIReporter();
  231. $this->__setGetVars();
  232. if ($this->type == 'all') {
  233. return TestManager::runAllTests($reporter);
  234. }
  235. if ($this->doCoverage) {
  236. if (!extension_loaded('xdebug')) {
  237. $this->out('You must install Xdebug to use the CakePHP(tm) Code Coverage Analyzation. Download it from http://www.xdebug.org/docs/install');
  238. exit(0);
  239. }
  240. }
  241. if ($this->type == 'group') {
  242. $ucFirstGroup = ucfirst($this->file);
  243. $path = CORE_TEST_GROUPS;
  244. if ($this->category == 'app') {
  245. $path = APP_TEST_GROUPS;
  246. } elseif ($this->isPluginTest) {
  247. $path = APP.'plugins'.DS.$this->category.DS.'tests'.DS.'groups';
  248. }
  249. if ($this->doCoverage) {
  250. require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
  251. CodeCoverageManager::start($ucFirstGroup, $reporter);
  252. }
  253. $result = TestManager::runGroupTest($ucFirstGroup, $reporter);
  254. if ($this->doCoverage) {
  255. CodeCoverageManager::report();
  256. }
  257. return $result;
  258. }
  259. $case = 'libs'.DS.$this->file.'.test.php';
  260. if ($this->category == 'app') {
  261. $case = $this->file.'.test.php';
  262. } elseif ($this->isPluginTest) {
  263. $case = $this->file.'.test.php';
  264. }
  265. if ($this->doCoverage) {
  266. require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
  267. CodeCoverageManager::start($case, $reporter);
  268. }
  269. $result = TestManager::runTestCase($case, $reporter);
  270. if ($this->doCoverage) {
  271. CodeCoverageManager::report();
  272. }
  273. return $result;
  274. }
  275. /**
  276. * Finds the correct folder to look for tests for based on the input category
  277. *
  278. * @return string the folder path
  279. * @access private
  280. */
  281. function __findFolderByCategory($category) {
  282. $folder = '';
  283. $paths = array(
  284. 'core' => CAKE,
  285. 'app' => APP
  286. );
  287. if (array_key_exists($category, $paths)) {
  288. $folder = $paths[$category];
  289. } else {
  290. $folder = APP.'plugins'.DS.Inflector::underscore($category).DS;
  291. }
  292. return $folder.'tests';
  293. }
  294. /**
  295. * Sets some get vars needed for TestManager
  296. *
  297. * @return void
  298. * @access private
  299. */
  300. function __setGetVars() {
  301. if (in_array($this->category, $this->plugins)) {
  302. $_GET['plugin'] = $this->category;
  303. } elseif (in_array(Inflector::Humanize($this->category), $this->plugins)) {
  304. $_GET['plugin'] = Inflector::Humanize($this->category);
  305. } elseif ($this->category == 'app') {
  306. $_GET['app'] = true;
  307. }
  308. if ($this->type == 'group') {
  309. $_GET['group'] = true;
  310. }
  311. }
  312. /**
  313. * tries to install simpletest and exits gracefully if it is not there
  314. *
  315. * @return void
  316. * @access private
  317. */
  318. function __installSimpleTest() {
  319. if (!App::import('Vendor', 'simpletest' . DS . 'reporter')) {
  320. $this->err('Sorry, Simpletest could not be found. Download it from http://simpletest.org and install it to your vendors directory.');
  321. exit;
  322. }
  323. }
  324. }
  325. ?>