1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26: class TestSuiteShell extends Shell {
27: 28: 29: 30: 31: 32:
33: var $category = '';
34: 35: 36: 37: 38: 39:
40: var $type = '';
41: 42: 43: 44: 45: 46:
47: var $file = '';
48: 49: 50: 51: 52: 53:
54: var $plugins = array();
55: 56: 57: 58: 59: 60:
61: var $isPluginTest = false;
62: 63: 64: 65: 66: 67:
68: var $doCoverage = false;
69: 70: 71: 72: 73: 74:
75: var $headline = 'CakePHP Test Shell';
76: 77: 78: 79: 80: 81:
82: function initialize() {
83: $corePath = Configure::corePaths('cake');
84: if (isset($corePath[0])) {
85: define('TEST_CAKE_CORE_INCLUDE_PATH', rtrim($corePath[0], DS) . DS);
86: } else {
87: define('TEST_CAKE_CORE_INCLUDE_PATH', CAKE_CORE_INCLUDE_PATH);
88: }
89:
90: $this->__installSimpleTest();
91:
92: require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_manager.php';
93: require_once CAKE . 'tests' . DS . 'lib' . DS . 'cli_reporter.php';
94:
95: $plugins = Configure::listObjects('plugin');
96: foreach ($plugins as $p) {
97: $this->plugins[] = Inflector::underscore($p);
98: }
99: }
100: 101: 102: 103: 104: 105:
106: function main() {
107: $this->out($this->headline);
108: $this->hr();
109:
110: if (count($this->args) > 0) {
111: $this->category = $this->args[0];
112:
113: if (!in_array($this->category, array('app', 'core'))) {
114: $this->isPluginTest = true;
115: }
116:
117: if (isset($this->args[1])) {
118: $this->type = $this->args[1];
119: }
120:
121: if (isset($this->args[2])) {
122: if ($this->args[2] == 'cov') {
123: $this->doCoverage = true;
124: } else {
125: $this->file = Inflector::underscore($this->args[2]);
126: }
127: }
128:
129: if (isset($this->args[3]) && $this->args[3] == 'cov') {
130: $this->doCoverage = true;
131: }
132: } else {
133: $this->err('Sorry, you did not pass any arguments!');
134: }
135:
136: if ($this->__canRun()) {
137: $this->out('Running '.$this->category.' '.$this->type.' '.$this->file);
138:
139: $exitCode = 0;
140: if (!$this->__run()) {
141: $exitCode = 1;
142: }
143: exit($exitCode);
144: } else {
145: $this->err('Sorry, the tests could not be found.');
146: exit(1);
147: }
148: }
149: 150: 151: 152: 153: 154:
155: function help() {
156: $this->out('Usage: ');
157: $this->out("\tcake testsuite category test_type file");
158: $this->out("\t\t- category - \"app\", \"core\" or name of a plugin");
159: $this->out("\t\t- test_type - \"case\", \"group\" or \"all\"");
160: $this->out("\t\t- test_file - file name with folder prefix and without the (test|group).php suffix");
161: $this->out('');
162: $this->out('Examples: ');
163: $this->out("\t\tcake testsuite app all");
164: $this->out("\t\tcake testsuite core all");
165: $this->out('');
166: $this->out("\t\tcake testsuite app case behaviors/debuggable");
167: $this->out("\t\tcake testsuite app case models/my_model");
168: $this->out("\t\tcake testsuite app case controllers/my_controller");
169: $this->out('');
170: $this->out("\t\tcake testsuite core case file");
171: $this->out("\t\tcake testsuite core case router");
172: $this->out("\t\tcake testsuite core case set");
173: $this->out('');
174: $this->out("\t\tcake testsuite app group mygroup");
175: $this->out("\t\tcake testsuite core group acl");
176: $this->out("\t\tcake testsuite core group socket");
177: $this->out('');
178: $this->out("\t\tcake testsuite bugs case models/bug");
179: $this->out("\t\t // for the plugin 'bugs' and its test case 'models/bug'");
180: $this->out("\t\tcake testsuite bugs group bug");
181: $this->out("\t\t // for the plugin bugs and its test group 'bug'");
182: $this->out('');
183: $this->out('Code Coverage Analysis: ');
184: $this->out("\n\nAppend 'cov' to any of the above in order to enable code coverage analysis");
185: }
186: 187: 188: 189: 190: 191:
192: function __canRun() {
193: $isNeitherAppNorCore = !in_array($this->category, array('app', 'core'));
194: $isPlugin = in_array(Inflector::underscore($this->category), $this->plugins);
195:
196: if ($isNeitherAppNorCore && !$isPlugin) {
197: $this->err($this->category.' is an invalid test category (either "app", "core" or name of a plugin)');
198: return false;
199: }
200:
201: $folder = $this->__findFolderByCategory($this->category);
202: if (!file_exists($folder)) {
203: $this->err($folder . ' not found');
204: return false;
205: }
206:
207: if (!in_array($this->type, array('all', 'group', 'case'))) {
208: $this->err($this->type.' is invalid. Should be case, group or all');
209: return false;
210: }
211:
212: switch ($this->type) {
213: case 'all':
214: return true;
215: break;
216: case 'group':
217: if (file_exists($folder.DS.'groups'.DS.$this->file.'.group.php')) {
218: return true;
219: }
220: break;
221: case 'case':
222: if ($this->category == 'app' && file_exists($folder.DS.'cases'.DS.$this->file.'.test.php')) {
223: return true;
224: }
225:
226: if ($this->category == 'core' && file_exists($folder.DS.'cases'.DS.'libs'.DS.$this->file.'.test.php')) {
227: return true;
228: }
229:
230: if ($isPlugin && file_exists($folder.DS.'cases'.DS.$this->file.'.test.php')) {
231: return true;
232: }
233: break;
234: }
235:
236: $this->err($this->category.' '.$this->type.' '.$this->file.' is an invalid test identifier');
237: return false;
238: }
239: 240: 241: 242: 243: 244:
245: function __run() {
246: $reporter = new CLIReporter();
247: $this->__setGetVars();
248:
249: if ($this->type == 'all') {
250: return TestManager::runAllTests($reporter);
251: }
252:
253: if ($this->doCoverage) {
254: if (!extension_loaded('xdebug')) {
255: $this->out('You must install Xdebug to use the CakePHP(tm) Code Coverage Analyzation. Download it from http://www.xdebug.org/docs/install');
256: exit(0);
257: }
258: }
259:
260: if ($this->type == 'group') {
261: $ucFirstGroup = ucfirst($this->file);
262:
263: $path = CORE_TEST_GROUPS;
264: if ($this->category == 'app') {
265: $path = APP_TEST_GROUPS;
266: } elseif ($this->isPluginTest) {
267: $path = APP.'plugins'.DS.$this->category.DS.'tests'.DS.'groups';
268: }
269:
270: if ($this->doCoverage) {
271: require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
272: CodeCoverageManager::start($ucFirstGroup, $reporter);
273: }
274: $result = TestManager::runGroupTest($ucFirstGroup, $reporter);
275: if ($this->doCoverage) {
276: CodeCoverageManager::report();
277: }
278: return $result;
279: }
280:
281: $case = 'libs'.DS.$this->file.'.test.php';
282: if ($this->category == 'app') {
283: $case = $this->file.'.test.php';
284: } elseif ($this->isPluginTest) {
285: $case = $this->file.'.test.php';
286: }
287:
288: if ($this->doCoverage) {
289: require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
290: CodeCoverageManager::start($case, $reporter);
291: }
292:
293: $result = TestManager::runTestCase($case, $reporter);
294: if ($this->doCoverage) {
295: CodeCoverageManager::report();
296: }
297:
298: return $result;
299: }
300: 301: 302: 303: 304: 305:
306: function __findFolderByCategory($category) {
307: $folder = '';
308: $paths = array(
309: 'core' => CAKE,
310: 'app' => APP
311: );
312:
313: if (array_key_exists($category, $paths)) {
314: $folder = $paths[$category] . 'tests';
315: } else {
316: $scoredCategory = Inflector::underscore($category);
317: $folder = APP . 'plugins' . DS . $scoredCategory . DS;
318: $pluginPaths = Configure::read('pluginPaths');
319: foreach ($pluginPaths as $path) {
320: if (file_exists($path . $scoredCategory . DS . 'tests')) {
321: $folder = $path . $scoredCategory . DS . 'tests';
322: break;
323: }
324: }
325: }
326: return $folder;
327: }
328: 329: 330: 331: 332: 333:
334: function __setGetVars() {
335: if (in_array($this->category, $this->plugins)) {
336: $_GET['plugin'] = $this->category;
337: } elseif (in_array(Inflector::Humanize($this->category), $this->plugins)) {
338: $_GET['plugin'] = Inflector::Humanize($this->category);
339: } elseif ($this->category == 'app') {
340: $_GET['app'] = true;
341: }
342: if ($this->type == 'group') {
343: $_GET['group'] = true;
344: }
345: }
346: 347: 348: 349: 350: 351:
352: function __installSimpleTest() {
353: if (!App::import('Vendor', 'simpletest' . DS . 'reporter')) {
354: $this->err('Sorry, Simpletest could not be found. Download it from http://simpletest.org and install it to your vendors directory.');
355: exit;
356: }
357: }
358: }
359: ?>