~tsep-dev/tsep/0.9-beta

« back to all changes in this revision

Viewing changes to branches/symfony/cake/console/libs/testsuite.php

  • Committer: geoffreyfishing
  • Date: 2011-01-11 23:46:12 UTC
  • Revision ID: svn-v4:ae0de26e-ed09-4cbe-9a20-e40b4c60ac6c::125
Created a symfony branch for future migration to symfony

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 versions 4 and 5
 
8
 *
 
9
 * CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
 
10
 * Copyright 2005-2010, 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-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
 
16
 * @link          http://book.cakephp.org/view/1196/Testing 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
/**
 
25
 * The test category, "app", "core" or the name of a plugin
 
26
 *
 
27
 * @var string
 
28
 * @access public
 
29
 */
 
30
        var $category = '';
 
31
 
 
32
/**
 
33
 * "group", "case" or "all"
 
34
 *
 
35
 * @var string
 
36
 * @access public
 
37
 */
 
38
        var $type = '';
 
39
 
 
40
/**
 
41
 * Path to the test case/group file
 
42
 *
 
43
 * @var string
 
44
 * @access public
 
45
 */
 
46
        var $file = '';
 
47
 
 
48
/**
 
49
 * Storage for plugins that have tests
 
50
 *
 
51
 * @var string
 
52
 * @access public
 
53
 */
 
54
        var $plugins = array();
 
55
 
 
56
/**
 
57
 * Convenience variable to avoid duplicated code
 
58
 *
 
59
 * @var string
 
60
 * @access public
 
61
 */
 
62
        var $isPluginTest = false;
 
63
 
 
64
/**
 
65
 * Stores if the user wishes to get a code coverage analysis report
 
66
 *
 
67
 * @var string
 
68
 * @access public
 
69
 */
 
70
        var $doCoverage = false;
 
71
 
 
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
 
 
86
                $this->__installSimpleTest();
 
87
 
 
88
                require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_manager.php';
 
89
                require_once CAKE . 'tests' . DS . 'lib' . DS . 'reporter' . DS . 'cake_cli_reporter.php';
 
90
 
 
91
                $plugins = App::objects('plugin');
 
92
                foreach ($plugins as $p) {
 
93
                        $this->plugins[] = Inflector::underscore($p);
 
94
                }
 
95
                $this->parseArgs();
 
96
                $this->getManager();
 
97
        }
 
98
 
 
99
/**
 
100
 * Parse the arguments given into the Shell object properties.
 
101
 *
 
102
 * @return void
 
103
 * @access public
 
104
 */
 
105
        function parseArgs() {
 
106
                if (empty($this->args)) {
 
107
                        return;
 
108
                }
 
109
                $this->category = $this->args[0];
 
110
 
 
111
                if (!in_array($this->category, array('app', 'core'))) {
 
112
                        $this->isPluginTest = true;
 
113
                }
 
114
 
 
115
                if (isset($this->args[1])) {
 
116
                        $this->type = $this->args[1];
 
117
                }
 
118
 
 
119
                if (isset($this->args[2])) {
 
120
                        if ($this->args[2] == 'cov') {
 
121
                                $this->doCoverage = true;
 
122
                        } else {
 
123
                                $this->file = Inflector::underscore($this->args[2]);
 
124
                        }
 
125
                }
 
126
 
 
127
                if (isset($this->args[3]) && $this->args[3] == 'cov') {
 
128
                        $this->doCoverage = true;
 
129
                }
 
130
        }
 
131
 
 
132
/**
 
133
 * Gets a manager instance, and set the app/plugin properties.
 
134
 *
 
135
 * @return void
 
136
 */
 
137
        function getManager() {
 
138
                $this->Manager = new TestManager();
 
139
                $this->Manager->appTest = ($this->category === 'app');
 
140
                if ($this->isPluginTest) {
 
141
                        $this->Manager->pluginTest = $this->category;
 
142
                }
 
143
        }
 
144
 
 
145
/**
 
146
 * Main entry point to this shell
 
147
 *
 
148
 * @return void
 
149
 * @access public
 
150
 */
 
151
        function main() {
 
152
                $this->out(__('CakePHP Test Shell', true));
 
153
                $this->hr();
 
154
 
 
155
                if (count($this->args) == 0) {
 
156
                        $this->error(__('Sorry, you did not pass any arguments!', true));
 
157
                }
 
158
 
 
159
                if ($this->__canRun()) {
 
160
                        $message = sprintf(__('Running %s %s %s', true), $this->category, $this->type, $this->file);
 
161
                        $this->out($message);
 
162
 
 
163
                        $exitCode = 0;
 
164
                        if (!$this->__run()) {
 
165
                                $exitCode = 1;
 
166
                        }
 
167
                        $this->_stop($exitCode);
 
168
                } else {
 
169
                        $this->error(__('Sorry, the tests could not be found.', true));
 
170
                }
 
171
        }
 
172
 
 
173
/**
 
174
 * Help screen
 
175
 *
 
176
 * @return void
 
177
 * @access public
 
178
 */
 
179
        function help() {
 
180
                $this->out('Usage: ');
 
181
                $this->out("\tcake testsuite category test_type file");
 
182
                $this->out("\t\t- category - \"app\", \"core\" or name of a plugin");
 
183
                $this->out("\t\t- test_type - \"case\", \"group\" or \"all\"");
 
184
                $this->out("\t\t- test_file - file name with folder prefix and without the (test|group).php suffix");
 
185
                $this->out();
 
186
                $this->out('Examples: ');
 
187
                $this->out("\t\tcake testsuite app all");
 
188
                $this->out("\t\tcake testsuite core all");
 
189
                $this->out();
 
190
                $this->out("\t\tcake testsuite app case behaviors/debuggable");
 
191
                $this->out("\t\tcake testsuite app case models/my_model");
 
192
                $this->out("\t\tcake testsuite app case controllers/my_controller");
 
193
                $this->out();
 
194
                $this->out("\t\tcake testsuite core case file");
 
195
                $this->out("\t\tcake testsuite core case router");
 
196
                $this->out("\t\tcake testsuite core case set");
 
197
                $this->out();
 
198
                $this->out("\t\tcake testsuite app group mygroup");
 
199
                $this->out("\t\tcake testsuite core group acl");
 
200
                $this->out("\t\tcake testsuite core group socket");
 
201
                $this->out();
 
202
                $this->out("\t\tcake testsuite bugs case models/bug");
 
203
                $this->out("\t\t  // for the plugin 'bugs' and its test case 'models/bug'");
 
204
                $this->out("\t\tcake testsuite bugs group bug");
 
205
                $this->out("\t\t  // for the plugin bugs and its test group 'bug'");
 
206
                $this->out();
 
207
                $this->out('Code Coverage Analysis: ');
 
208
                $this->out("\n\nAppend 'cov' to any of the above in order to enable code coverage analysis");
 
209
        }
 
210
 
 
211
/**
 
212
 * Checks if the arguments supplied point to a valid test file and thus the shell can be run.
 
213
 *
 
214
 * @return bool true if it's a valid test file, false otherwise
 
215
 * @access private
 
216
 */
 
217
        function __canRun() {
 
218
                $isNeitherAppNorCore = !in_array($this->category, array('app', 'core'));
 
219
                $isPlugin = in_array(Inflector::underscore($this->category), $this->plugins);
 
220
 
 
221
                if ($isNeitherAppNorCore && !$isPlugin) {
 
222
                        $message = sprintf(
 
223
                                __('%s is an invalid test category (either "app", "core" or name of a plugin)', true),
 
224
                                $this->category
 
225
                        );
 
226
                        $this->error($message);
 
227
                        return false;
 
228
                }
 
229
 
 
230
                $folder = $this->__findFolderByCategory($this->category);
 
231
                if (!file_exists($folder)) {
 
232
                        $this->err(sprintf(__('%s not found', true), $folder));
 
233
                        return false;
 
234
                }
 
235
 
 
236
                if (!in_array($this->type, array('all', 'group', 'case'))) {
 
237
                        $this->err(sprintf(__('%s is invalid. Should be case, group or all', true), $this->type));
 
238
                        return false;
 
239
                }
 
240
 
 
241
                $fileName = $this->__getFileName($folder, $this->isPluginTest);
 
242
                if ($fileName === true || file_exists($folder . $fileName)) {
 
243
                        return true;
 
244
                }
 
245
 
 
246
                $message = sprintf(
 
247
                        __('%s %s %s is an invalid test identifier', true),
 
248
                        $this->category, $this->type, $this->file
 
249
                );
 
250
                $this->err($message);
 
251
                return false;
 
252
        }
 
253
/**
 
254
 * Executes the tests depending on our settings
 
255
 *
 
256
 * @return void
 
257
 * @access private
 
258
 */
 
259
        function __run() {
 
260
                $Reporter = new CakeCliReporter('utf-8', array(
 
261
                        'app' => $this->Manager->appTest,
 
262
                        'plugin' => $this->Manager->pluginTest,
 
263
                        'group' => ($this->type === 'group'),
 
264
                        'codeCoverage' => $this->doCoverage
 
265
                ));
 
266
 
 
267
                if ($this->type == 'all') {
 
268
                        return $this->Manager->runAllTests($Reporter);
 
269
                }
 
270
 
 
271
                if ($this->doCoverage) {
 
272
                        if (!extension_loaded('xdebug')) {
 
273
                                $this->out(__('You must install Xdebug to use the CakePHP(tm) Code Coverage Analyzation. Download it from http://www.xdebug.org/docs/install', true));
 
274
                                $this->_stop(0);
 
275
                        }
 
276
                }
 
277
 
 
278
                if ($this->type == 'group') {
 
279
                        $ucFirstGroup = ucfirst($this->file);
 
280
                        if ($this->doCoverage) {
 
281
                                require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
 
282
                                CodeCoverageManager::init($ucFirstGroup, $Reporter);
 
283
                                CodeCoverageManager::start();
 
284
                        }
 
285
                        $result = $this->Manager->runGroupTest($ucFirstGroup, $Reporter);
 
286
                        return $result;
 
287
                }
 
288
 
 
289
                $folder = $folder = $this->__findFolderByCategory($this->category);
 
290
                $case = $this->__getFileName($folder, $this->isPluginTest);
 
291
 
 
292
                if ($this->doCoverage) {
 
293
                        require_once CAKE . 'tests' . DS . 'lib' . DS . 'code_coverage_manager.php';
 
294
                        CodeCoverageManager::init($case, $Reporter);
 
295
                        CodeCoverageManager::start();
 
296
                }
 
297
                $result = $this->Manager->runTestCase($case, $Reporter);
 
298
                return $result;
 
299
        }
 
300
 
 
301
/**
 
302
 * Gets the concrete filename for the inputted test name and category/type
 
303
 *
 
304
 * @param string $folder Folder name to look for files in.
 
305
 * @param boolean $isPlugin If the test case is a plugin.
 
306
 * @return mixed Either string filename or boolean false on failure. Or true if the type is 'all'
 
307
 * @access private
 
308
 */
 
309
        function __getFileName($folder, $isPlugin) {
 
310
                $ext = $this->Manager->getExtension($this->type);
 
311
                switch ($this->type) {
 
312
                        case 'all':
 
313
                                return true;
 
314
                        case 'group':
 
315
                                return $this->file . $ext; 
 
316
                        case 'case':
 
317
                                if ($this->category == 'app' || $isPlugin) {
 
318
                                        return $this->file . $ext;
 
319
                                }
 
320
                                $coreCase = $this->file . $ext;
 
321
                                $coreLibCase = 'libs' . DS . $this->file . $ext;
 
322
 
 
323
                                if ($this->category == 'core' && file_exists($folder . DS . $coreCase)) {
 
324
                                        return $coreCase;
 
325
                                } elseif ($this->category == 'core' && file_exists($folder . DS . $coreLibCase)) {
 
326
                                        return $coreLibCase;
 
327
                                }
 
328
                }
 
329
                return false;
 
330
        }
 
331
 
 
332
/**
 
333
 * Finds the correct folder to look for tests for based on the input category and type.
 
334
 *
 
335
 * @param string $category The category of the test.  Either 'app', 'core' or a plugin name.
 
336
 * @return string the folder path
 
337
 * @access private
 
338
 */
 
339
        function __findFolderByCategory($category) {
 
340
                $folder = '';
 
341
                $paths = array(
 
342
                        'core' => CAKE,
 
343
                        'app' => APP
 
344
                );
 
345
                $typeDir = $this->type === 'group' ? 'groups' : 'cases';
 
346
 
 
347
                if (array_key_exists($category, $paths)) {
 
348
                        $folder = $paths[$category] . 'tests' . DS . $typeDir . DS;
 
349
                } else {
 
350
                        $pluginPath = App::pluginPath($category);
 
351
                        if (is_dir($pluginPath . 'tests')) {
 
352
                                $folder = $pluginPath . 'tests' . DS . $typeDir . DS;
 
353
                        }
 
354
                }
 
355
                return $folder;
 
356
        }
 
357
 
 
358
/**
 
359
 * tries to install simpletest and exits gracefully if it is not there
 
360
 *
 
361
 * @return void
 
362
 * @access private
 
363
 */
 
364
        function __installSimpleTest() {
 
365
                if (!App::import('Vendor', 'simpletest' . DS . 'reporter')) {
 
366
                        $this->err(__('Sorry, Simpletest could not be found. Download it from http://simpletest.org and install it to your vendors directory.', true));
 
367
                        exit;
 
368
                }
 
369
        }
 
370
}