PageRenderTime 40ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/cake/console/libs/testsuite.php

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