PageRenderTime 62ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/vendors/shells/tasks/test.php

https://github.com/pedroelsner/bake_utf8
PHP | 528 lines | 344 code | 45 blank | 139 comment | 41 complexity | 67a849b11b092654ff4108f413679060 MD5 | raw file
  1. <?php
  2. /**
  3. * Arquivo que executa o comando 'bake_utf8 test'
  4. *
  5. * Compatível com PHP 4 e 5
  6. *
  7. * @filesource
  8. * @author Pedro Elsner <pedro.elsner@gmail.com>
  9. * @since v 1.0
  10. */
  11. include_once dirname(__FILE__) . DS . 'bake_utf8.php';
  12. /**
  13. * Test Task
  14. *
  15. * @use BakeUtf8Task
  16. * @package bake_utf8
  17. * @subpackage bake_utf8.test_task
  18. * @link http://www.github.com/pedroelsner/bake_utf8
  19. */
  20. class TestTask extends BakeUtf8Task
  21. {
  22. /**
  23. * Diret�rio
  24. *
  25. * @var string
  26. * @access public
  27. */
  28. var $path = TESTS;
  29. /**
  30. * Carrega todas as taks
  31. *
  32. * @var array
  33. * @access public
  34. */
  35. var $tasks = array('Template');
  36. /**
  37. * @var array
  38. * @access public
  39. */
  40. var $classTypes = array(
  41. 'Model',
  42. 'Controller',
  43. 'Component',
  44. 'Behavior',
  45. 'Helper'
  46. );
  47. /**
  48. * @var array
  49. * @access public
  50. */
  51. var $_fixtures = array();
  52. /**
  53. * Execute
  54. *
  55. * @access public
  56. */
  57. function execute()
  58. {
  59. if (empty($this->args))
  60. {
  61. $this->__interactive();
  62. }
  63. if (count($this->args) == 1)
  64. {
  65. $this->__interactive($this->args[0]);
  66. }
  67. if (count($this->args) > 1)
  68. {
  69. $type = Inflector::underscore($this->args[0]);
  70. if ($this->bake($type, $this->args[1]))
  71. {
  72. $this->out('done');
  73. }
  74. }
  75. }
  76. /**
  77. * Interactive
  78. *
  79. * @param string $type
  80. * @return
  81. * @access private
  82. */
  83. function __interactive($type = null)
  84. {
  85. $this->interactive = true;
  86. $this->hr();
  87. $this->out(__('Bake Tests', true));
  88. $this->out(sprintf(__("Path: %s", true), $this->path));
  89. $this->hr();
  90. if ($type)
  91. {
  92. $type = Inflector::camelize($type);
  93. if (!in_array($type, $this->classTypes))
  94. {
  95. $this->error(sprintf('Incorrect type provided. Please choose one of %s', implode(', ', $this->classTypes)));
  96. }
  97. }
  98. else
  99. {
  100. $type = $this->getObjectType();
  101. }
  102. $className = $this->getClassName($type);
  103. return $this->bake($type, $className);
  104. }
  105. /**
  106. * Bake
  107. *
  108. * @param string $type
  109. * @param string $className
  110. * @return boolean
  111. * @access private
  112. */
  113. function bake($type, $className) {
  114. if ($this->typeCanDetectFixtures($type) && $this->isLoadableClass($type, $className)) {
  115. $this->out(__('Bake is detecting possible fixtures..', true));
  116. $testSubject =& $this->buildTestSubject($type, $className);
  117. $this->generateFixtureList($testSubject);
  118. } elseif ($this->interactive) {
  119. $this->getUserFixtures();
  120. }
  121. $fullClassName = $this->getRealClassName($type, $className);
  122. $methods = array();
  123. if (class_exists($fullClassName)) {
  124. $methods = $this->getTestableMethods($fullClassName);
  125. }
  126. $mock = $this->hasMockClass($type, $fullClassName);
  127. $construction = $this->generateConstructor($type, $fullClassName);
  128. $plugin = null;
  129. if ($this->plugin) {
  130. $plugin = $this->plugin . '.';
  131. }
  132. $this->Template->set('fixtures', $this->_fixtures);
  133. $this->Template->set('plugin', $plugin);
  134. $this->Template->set(compact('className', 'methods', 'type', 'fullClassName', 'mock', 'construction'));
  135. $out = $this->Template->generate('classes', 'test');
  136. $filename = $this->testCaseFileName($type, $className);
  137. $made = $this->createFile($filename, $out);
  138. if ($made) {
  139. return $out;
  140. }
  141. return false;
  142. }
  143. /**
  144. * Get Objetct Type
  145. *
  146. * @return string
  147. * @access public
  148. */
  149. function getObjectType()
  150. {
  151. $this->hr();
  152. $this->out(__("Select an object type:", true));
  153. $this->hr();
  154. $keys = array();
  155. foreach ($this->classTypes as $key => $option)
  156. {
  157. $this->out(++$key . '. ' . $option);
  158. $keys[] = $key;
  159. }
  160. $keys[] = 'q';
  161. $selection = $this->in(__("Enter the type of object to bake a test for or (q)uit", true), $keys, 'q');
  162. if ($selection == 'q')
  163. {
  164. return $this->_stop();
  165. }
  166. return $this->classTypes[$selection - 1];
  167. }
  168. /**
  169. * Get Class Name
  170. *
  171. * @param string $objectType
  172. * @return string
  173. * @access public
  174. */
  175. function getClassName($objectType)
  176. {
  177. $type = strtolower($objectType);
  178. if ($this->plugin)
  179. {
  180. $path = Inflector::pluralize($type);
  181. if ($type === 'helper')
  182. {
  183. $path = 'views' . DS . $path;
  184. }
  185. elseif ($type === 'component')
  186. {
  187. $path = 'controllers' . DS . $path;
  188. }
  189. elseif ($type === 'behavior')
  190. {
  191. $path = 'models' . DS . $path;
  192. }
  193. $options = App::objects($type, App::pluginPath($this->plugin) . $path, false);
  194. }
  195. else
  196. {
  197. $options = App::objects($type);
  198. }
  199. $this->out(sprintf(__('Choose a %s class', true), $objectType));
  200. $keys = array();
  201. foreach ($options as $key => $option)
  202. {
  203. $this->out(++$key . '. ' . $option);
  204. $keys[] = $key;
  205. }
  206. $selection = $this->in(__('Choose an existing class, or enter the name of a class that does not exist', true));
  207. if (isset($options[$selection - 1]))
  208. {
  209. return $options[$selection - 1];
  210. }
  211. return $selection;
  212. }
  213. /**
  214. * Type Can Detect Fixtures
  215. *
  216. * @param string $type
  217. * @return boolean
  218. * @access public
  219. */
  220. function typeCanDetectFixtures($type) {
  221. $type = strtolower($type);
  222. return ($type == 'controller' || $type == 'model');
  223. }
  224. /**
  225. * Is Loadable Class
  226. *
  227. * @param string $type
  228. * @param string $class
  229. * @return object
  230. * @access public
  231. */
  232. function isLoadableClass($type, $class)
  233. {
  234. return App::import($type, $class);
  235. }
  236. /**
  237. * Build Test Subject
  238. *
  239. * @param string $type
  240. * @param string $class
  241. * @return object
  242. * @access public
  243. */
  244. function &buildTestSubject($type, $class)
  245. {
  246. ClassRegistry::flush();
  247. App::import($type, $class);
  248. $class = $this->getRealClassName($type, $class);
  249. if (strtolower($type) == 'model')
  250. {
  251. $instance =& ClassRegistry::init($class);
  252. }
  253. else
  254. {
  255. $instance =& new $class();
  256. }
  257. return $instance;
  258. }
  259. /**
  260. * Get Real Class Name
  261. *
  262. * @param string $type
  263. * @param string $class
  264. * @return string
  265. * @access public
  266. */
  267. function getRealClassName($type, $class) {
  268. if (strtolower($type) == 'model') {
  269. return $class;
  270. }
  271. return $class . $type;
  272. }
  273. /**
  274. * Get Testable Methods
  275. *
  276. * @param string $className
  277. * @return string
  278. * @access public
  279. */
  280. function getTestableMethods($className)
  281. {
  282. $classMethods = get_class_methods($className);
  283. $parentMethods = get_class_methods(get_parent_class($className));
  284. $thisMethods = array_diff($classMethods, $parentMethods);
  285. $out = array();
  286. foreach ($thisMethods as $method)
  287. {
  288. if (substr($method, 0, 1) != '_' && $method != strtolower($className))
  289. {
  290. $out[] = $method;
  291. }
  292. }
  293. return $out;
  294. }
  295. /**
  296. * Generate Fixture List
  297. *
  298. * @param object $subject
  299. * @return array
  300. * @access public
  301. */
  302. function generateFixtureList(&$subject)
  303. {
  304. $this->_fixtures = array();
  305. if (is_a($subject, 'Model'))
  306. {
  307. $this->_processModel($subject);
  308. }
  309. elseif (is_a($subject, 'Controller'))
  310. {
  311. $this->_processController($subject);
  312. }
  313. return array_values($this->_fixtures);
  314. }
  315. /**
  316. * Process Model
  317. *
  318. * @param object $subject
  319. * @access protected
  320. */
  321. function _processModel(&$subject)
  322. {
  323. $this->_addFixture($subject->name);
  324. $associated = $subject->getAssociated();
  325. foreach ($associated as $alias => $type)
  326. {
  327. $className = $subject->{$alias}->name;
  328. if (!isset($this->_fixtures[$className]))
  329. {
  330. $this->_processModel($subject->{$alias});
  331. }
  332. if ($type == 'hasAndBelongsToMany')
  333. {
  334. $joinModel = Inflector::classify($subject->hasAndBelongsToMany[$alias]['joinTable']);
  335. if (!isset($this->_fixtures[$joinModel]))
  336. {
  337. $this->_processModel($subject->{$joinModel});
  338. }
  339. }
  340. }
  341. }
  342. /**
  343. * Process Controller
  344. *
  345. * @param object $subject
  346. * @access protected
  347. */
  348. function _processController(&$subject)
  349. {
  350. $subject->constructClasses();
  351. $models = array(Inflector::classify($subject->name));
  352. if (!empty($subject->uses))
  353. {
  354. $models = $subject->uses;
  355. }
  356. foreach ($models as $model)
  357. {
  358. $this->_processModel($subject->{$model});
  359. }
  360. }
  361. /**
  362. * Add Fixture
  363. *
  364. * @param string $name
  365. * @access protected
  366. */
  367. function _addFixture($name)
  368. {
  369. $parent = get_parent_class($name);
  370. $prefix = 'app.';
  371. if (strtolower($parent) != 'appmodel' && strtolower(substr($parent, -8)) == 'appmodel')
  372. {
  373. $pluginName = substr($parent, 0, strlen($parent) -8);
  374. $prefix = 'plugin.' . Inflector::underscore($pluginName) . '.';
  375. }
  376. $fixture = $prefix . Inflector::underscore($name);
  377. $this->_fixtures[$name] = $fixture;
  378. }
  379. /**
  380. * Get User Fixture
  381. *
  382. * @return array
  383. * @access public
  384. */
  385. function getUserFixtures()
  386. {
  387. $proceed = $this->in(__('Bake could not detect fixtures, would you like to add some?', true), array('y','n'), 'n');
  388. $fixtures = array();
  389. if (strtolower($proceed) == 'y')
  390. {
  391. $fixtureList = $this->in(__("Please provide a comma separated list of the fixtures names you'd like to use.\nExample: 'app.comment, app.post, plugin.forums.post'", true));
  392. $fixtureListTrimmed = str_replace(' ', '', $fixtureList);
  393. $fixtures = explode(',', $fixtureListTrimmed);
  394. }
  395. $this->_fixtures = array_merge($this->_fixtures, $fixtures);
  396. return $fixtures;
  397. }
  398. /**
  399. * Has Mock Class
  400. *
  401. * @param string $type
  402. * @return string
  403. * @access public
  404. */
  405. function hasMockClass($type) {
  406. $type = strtolower($type);
  407. return $type == 'controller';
  408. }
  409. /**
  410. * Generate Constructor
  411. *
  412. * @param string $type
  413. * @param string $fullClassName
  414. * @return string
  415. * @access public
  416. */
  417. function generateConstructor($type, $fullClassName)
  418. {
  419. $type = strtolower($type);
  420. if ($type == 'model')
  421. {
  422. return "ClassRegistry::init('$fullClassName');\n";
  423. }
  424. if ($type == 'controller')
  425. {
  426. $className = substr($fullClassName, 0, strlen($fullClassName) - 10);
  427. return "new Test$fullClassName();\n\t\t\$this->{$className}->constructClasses();\n";
  428. }
  429. return "new $fullClassName();\n";
  430. }
  431. /**
  432. * Test Case File Name
  433. *
  434. * @param string $type
  435. * @param string $className
  436. * @return string
  437. * @access public
  438. */
  439. function testCaseFileName($type, $className)
  440. {
  441. $path = $this->getPath();;
  442. $path .= 'cases' . DS . strtolower($type) . 's' . DS;
  443. if (strtolower($type) == 'controller')
  444. {
  445. $className = $this->getRealClassName($type, $className);
  446. }
  447. return $path . Inflector::underscore($className) . '.test.php';
  448. }
  449. /**
  450. * Help
  451. *
  452. * Responde o comando 'bake_utf8 test help'
  453. *
  454. * @access public
  455. */
  456. function help() {
  457. $this->hr();
  458. $this->out("Usage: cake bake_utf8 test <type> <class>");
  459. $this->hr();
  460. $this->out('Commands:');
  461. $this->out("");
  462. $this->out("test model post\n\tbakes a test case for the post model.");
  463. $this->out("");
  464. $this->out("test controller comments\n\tbakes a test case for the comments controller.");
  465. $this->out("");
  466. $this->out('Arguments:');
  467. $this->out("\t<type> Can be any of the following 'controller', 'model', 'helper',\n\t'component', 'behavior'.");
  468. $this->out("\t<class> Any existing class for the chosen type.");
  469. $this->out("");
  470. $this->out("Parameters:");
  471. $this->out("\t-plugin CamelCased name of plugin to bake tests for.");
  472. $this->out("");
  473. $this->_stop();
  474. }
  475. }