CakeTestSuiteDispatcher.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <?php
  2. /**
  3. * CakeTestSuiteDispatcher controls dispatching TestSuite web based requests.
  4. *
  5. * PHP 5
  6. *
  7. * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
  8. * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * Redistributions of files must retain the above copyright notice
  12. *
  13. * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. * @link http://cakephp.org CakePHP(tm) Project
  15. * @package Cake.TestSuite
  16. * @since CakePHP(tm) v 1.3
  17. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  18. */
  19. define('CORE_TEST_CASES', CAKE . 'Test' . DS . 'Case');
  20. define('APP_TEST_CASES', TESTS . 'Case');
  21. App::uses('CakeTestSuiteCommand', 'TestSuite');
  22. /**
  23. * CakeTestSuiteDispatcher handles web requests to the test suite and runs the correct action.
  24. *
  25. * @package Cake.TestSuite
  26. */
  27. class CakeTestSuiteDispatcher {
  28. /**
  29. * 'Request' parameters
  30. *
  31. * @var array
  32. */
  33. public $params = array(
  34. 'codeCoverage' => false,
  35. 'case' => null,
  36. 'core' => false,
  37. 'app' => true,
  38. 'plugin' => null,
  39. 'output' => 'html',
  40. 'show' => 'groups',
  41. 'show_passes' => false,
  42. 'filter' => false,
  43. 'fixture' => null
  44. );
  45. /**
  46. * Baseurl for the request
  47. *
  48. * @var string
  49. */
  50. protected $_baseUrl;
  51. /**
  52. * Base dir of the request. Used for accessing assets.
  53. *
  54. * @var string
  55. */
  56. protected $_baseDir;
  57. /**
  58. * boolean to set auto parsing of params.
  59. *
  60. * @var boolean
  61. */
  62. protected $_paramsParsed = false;
  63. /**
  64. * reporter instance used for the request
  65. *
  66. * @var CakeBaseReporter
  67. */
  68. protected static $_Reporter = null;
  69. /**
  70. * constructor
  71. *
  72. * @return void
  73. */
  74. public function __construct() {
  75. $this->_baseUrl = $_SERVER['PHP_SELF'];
  76. $dir = rtrim(dirname($this->_baseUrl), '\\');
  77. $this->_baseDir = ($dir === '/') ? $dir : $dir . '/';
  78. }
  79. /**
  80. * Runs the actions required by the URL parameters.
  81. *
  82. * @return void
  83. */
  84. public function dispatch() {
  85. $this->_checkPHPUnit();
  86. $this->_parseParams();
  87. if ($this->params['case']) {
  88. $value = $this->_runTestCase();
  89. } else {
  90. $value = $this->_testCaseList();
  91. }
  92. $output = ob_get_clean();
  93. echo $output;
  94. return $value;
  95. }
  96. /**
  97. * Static method to initialize the test runner, keeps global space clean
  98. *
  99. * @return void
  100. */
  101. public static function run() {
  102. $dispatcher = new CakeTestSuiteDispatcher();
  103. $dispatcher->dispatch();
  104. }
  105. /**
  106. * Checks that PHPUnit is installed. Will exit if it doesn't
  107. *
  108. * @return void
  109. */
  110. protected function _checkPHPUnit() {
  111. $found = $this->loadTestFramework();
  112. if (!$found) {
  113. $baseDir = $this->_baseDir;
  114. include CAKE . 'TestSuite' . DS . 'templates' . DS . 'phpunit.php';
  115. exit();
  116. }
  117. }
  118. /**
  119. * Checks for the existence of the test framework files
  120. *
  121. * @return boolean true if found, false otherwise
  122. */
  123. public function loadTestFramework() {
  124. foreach (App::path('vendors') as $vendor) {
  125. if (is_dir($vendor . 'PHPUnit')) {
  126. ini_set('include_path', $vendor . PATH_SEPARATOR . ini_get('include_path'));
  127. break;
  128. }
  129. }
  130. return include 'PHPUnit' . DS . 'Autoload.php';
  131. }
  132. /**
  133. * Checks for the xdebug extension required to do code coverage. Displays an error
  134. * if xdebug isn't installed.
  135. *
  136. * @return void
  137. */
  138. protected function _checkXdebug() {
  139. if (!extension_loaded('xdebug')) {
  140. $baseDir = $this->_baseDir;
  141. include CAKE . 'TestSuite' . DS . 'templates' . DS . 'xdebug.php';
  142. exit();
  143. }
  144. }
  145. /**
  146. * Generates a page containing the a list of test cases that could be run.
  147. *
  148. * @return void
  149. */
  150. protected function _testCaseList() {
  151. $command = new CakeTestSuiteCommand('', $this->params);
  152. $Reporter = $command->handleReporter($this->params['output']);
  153. $Reporter->paintDocumentStart();
  154. $Reporter->paintTestMenu();
  155. $Reporter->testCaseList();
  156. $Reporter->paintDocumentEnd();
  157. }
  158. /**
  159. * Sets the params, calling this will bypass the auto parameter parsing.
  160. *
  161. * @param array $params Array of parameters for the dispatcher
  162. * @return void
  163. */
  164. public function setParams($params) {
  165. $this->params = $params;
  166. $this->_paramsParsed = true;
  167. }
  168. /**
  169. * Parse url params into a 'request'
  170. *
  171. * @return void
  172. */
  173. protected function _parseParams() {
  174. if (!$this->_paramsParsed) {
  175. if (!isset($_SERVER['SERVER_NAME'])) {
  176. $_SERVER['SERVER_NAME'] = '';
  177. }
  178. foreach ($this->params as $key => $value) {
  179. if (isset($_GET[$key])) {
  180. $this->params[$key] = $_GET[$key];
  181. }
  182. }
  183. if (isset($_GET['code_coverage'])) {
  184. $this->params['codeCoverage'] = true;
  185. $this->_checkXdebug();
  186. }
  187. }
  188. if (empty($this->params['plugin']) && empty($this->params['core'])) {
  189. $this->params['app'] = true;
  190. }
  191. $this->params['baseUrl'] = $this->_baseUrl;
  192. $this->params['baseDir'] = $this->_baseDir;
  193. }
  194. /**
  195. * Runs a test case file.
  196. *
  197. * @return void
  198. */
  199. protected function _runTestCase() {
  200. $commandArgs = array(
  201. 'case' => $this->params['case'],
  202. 'core' => $this->params['core'],
  203. 'app' => $this->params['app'],
  204. 'plugin' => $this->params['plugin'],
  205. 'codeCoverage' => $this->params['codeCoverage'],
  206. 'showPasses' => !empty($this->params['show_passes']),
  207. 'baseUrl' => $this->_baseUrl,
  208. 'baseDir' => $this->_baseDir,
  209. );
  210. $options = array(
  211. '--filter', $this->params['filter'],
  212. '--output', $this->params['output'],
  213. '--fixture', $this->params['fixture']
  214. );
  215. restore_error_handler();
  216. try {
  217. self::time();
  218. $command = new CakeTestSuiteCommand('CakeTestLoader', $commandArgs);
  219. $command->run($options);
  220. } catch (MissingConnectionException $exception) {
  221. ob_end_clean();
  222. $baseDir = $this->_baseDir;
  223. include CAKE . 'TestSuite' . DS . 'templates' . DS . 'missing_connection.php';
  224. exit();
  225. }
  226. }
  227. /**
  228. * Sets a static timestamp
  229. *
  230. * @param boolean $reset to set new static timestamp.
  231. * @return integer timestamp
  232. */
  233. public static function time($reset = false) {
  234. static $now;
  235. if ($reset || !$now) {
  236. $now = time();
  237. }
  238. return $now;
  239. }
  240. /**
  241. * Returns formatted date string using static time
  242. * This method is being used as formatter for created, modified and updated fields in Model::save()
  243. *
  244. * @param string $format format to be used.
  245. * @return string formatted date
  246. */
  247. public static function date($format) {
  248. return date($format, self::time());
  249. }
  250. }