統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / TestSuite / CakeTestSuiteDispatcher.php @ master

履歴 | 表示 | アノテート | ダウンロード (7.115 KB)

1
<?php
2
/**
3
 * CakeTestSuiteDispatcher controls dispatching TestSuite web based requests.
4
 *
5
 * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
6
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
7
 *
8
 * Licensed under The MIT License
9
 * For full copyright and license information, please see the LICENSE.txt
10
 * Redistributions of files must retain the above copyright notice
11
 *
12
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
13
 * @link          http://cakephp.org CakePHP(tm) Project
14
 * @package       Cake.TestSuite
15
 * @since         CakePHP(tm) v 1.3
16
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
17
 */
18

    
19
define('CORE_TEST_CASES', CAKE . 'Test' . DS . 'Case');
20
define('APP_TEST_CASES', TESTS . 'Case');
21

    
22
App::uses('CakeTestSuiteCommand', 'TestSuite');
23

    
24
/**
25
 * CakeTestSuiteDispatcher handles web requests to the test suite and runs the correct action.
26
 *
27
 * @package       Cake.TestSuite
28
 */
29
class CakeTestSuiteDispatcher {
30

    
31
/**
32
 * 'Request' parameters
33
 *
34
 * @var array
35
 */
36
        public $params = array(
37
                'codeCoverage' => false,
38
                'case' => null,
39
                'core' => false,
40
                'app' => false,
41
                'plugin' => null,
42
                'output' => 'html',
43
                'show' => 'groups',
44
                'show_passes' => false,
45
                'filter' => false,
46
                'fixture' => null
47
        );
48

    
49
/**
50
 * Baseurl for the request
51
 *
52
 * @var string
53
 */
54
        protected $_baseUrl;
55

    
56
/**
57
 * Base dir of the request. Used for accessing assets.
58
 *
59
 * @var string
60
 */
61
        protected $_baseDir;
62

    
63
/**
64
 * boolean to set auto parsing of params.
65
 *
66
 * @var bool
67
 */
68
        protected $_paramsParsed = false;
69

    
70
/**
71
 * reporter instance used for the request
72
 *
73
 * @var CakeBaseReporter
74
 */
75
        protected static $_Reporter = null;
76

    
77
/**
78
 * Constructor
79
 */
80
        public function __construct() {
81
                $this->_baseUrl = $_SERVER['PHP_SELF'];
82
                $dir = rtrim(dirname($this->_baseUrl), '\\');
83
                $this->_baseDir = ($dir === '/') ? $dir : $dir . '/';
84
        }
85

    
86
/**
87
 * Runs the actions required by the URL parameters.
88
 *
89
 * @return void
90
 */
91
        public function dispatch() {
92
                $this->_checkPHPUnit();
93
                $this->_parseParams();
94

    
95
                if ($this->params['case']) {
96
                        $value = $this->_runTestCase();
97
                } else {
98
                        $value = $this->_testCaseList();
99
                }
100

    
101
                $output = ob_get_clean();
102
                echo $output;
103
                return $value;
104
        }
105

    
106
/**
107
 * Static method to initialize the test runner, keeps global space clean
108
 *
109
 * @return void
110
 */
111
        public static function run() {
112
                $dispatcher = new CakeTestSuiteDispatcher();
113
                $dispatcher->dispatch();
114
        }
115

    
116
/**
117
 * Checks that PHPUnit is installed. Will exit if it doesn't
118
 *
119
 * @return void
120
 */
121
        protected function _checkPHPUnit() {
122
                $found = $this->loadTestFramework();
123
                if (!$found) {
124
                        $baseDir = $this->_baseDir;
125
                        include CAKE . 'TestSuite' . DS . 'templates' . DS . 'phpunit.php';
126
                        exit();
127
                }
128
        }
129

    
130
/**
131
 * Checks for the existence of the test framework files
132
 *
133
 * @return bool true if found, false otherwise
134
 */
135
        public function loadTestFramework() {
136
                if (class_exists('PHPUnit_Framework_TestCase')) {
137
                        return true;
138
                }
139
                $phpunitPath = 'phpunit' . DS . 'phpunit';
140
                if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
141
                        $composerGlobalDir[] = env('APPDATA') . DS . 'Composer' . DS . 'vendor' . DS;
142
                } else {
143
                        $composerGlobalDir[] = env('HOME') . DS . '.composer' . DS . 'vendor' . DS;
144
                }
145
                $vendors = array_merge(App::path('vendors'), $composerGlobalDir);
146
                foreach ($vendors as $vendor) {
147
                        $vendor = rtrim($vendor, DS);
148
                        if (is_dir($vendor . DS . $phpunitPath)) {
149
                                ini_set('include_path', $vendor . DS . $phpunitPath . PATH_SEPARATOR . ini_get('include_path'));
150
                                break;
151
                        } elseif (is_dir($vendor . DS . 'PHPUnit')) {
152
                                ini_set('include_path', $vendor . PATH_SEPARATOR . ini_get('include_path'));
153
                                break;
154
                        } elseif (is_file($vendor . DS . 'phpunit.phar')) {
155
                                $backup = $GLOBALS['_SERVER']['SCRIPT_NAME'];
156
                                $GLOBALS['_SERVER']['SCRIPT_NAME'] = '-';
157
                                $included = include_once $vendor . DS . 'phpunit.phar';
158
                                $GLOBALS['_SERVER']['SCRIPT_NAME'] = $backup;
159
                                return $included;
160
                        }
161
                }
162
                include 'PHPUnit' . DS . 'Autoload.php';
163
                return class_exists('PHPUnit_Framework_TestCase');
164
        }
165

    
166
/**
167
 * Checks for the xdebug extension required to do code coverage. Displays an error
168
 * if xdebug isn't installed.
169
 *
170
 * @return void
171
 */
172
        protected function _checkXdebug() {
173
                if (!extension_loaded('xdebug')) {
174
                        $baseDir = $this->_baseDir;
175
                        include CAKE . 'TestSuite' . DS . 'templates' . DS . 'xdebug.php';
176
                        exit();
177
                }
178
        }
179

    
180
/**
181
 * Generates a page containing the a list of test cases that could be run.
182
 *
183
 * @return void
184
 */
185
        protected function _testCaseList() {
186
                $command = new CakeTestSuiteCommand('', $this->params);
187
                $Reporter = $command->handleReporter($this->params['output']);
188
                $Reporter->paintDocumentStart();
189
                $Reporter->paintTestMenu();
190
                $Reporter->testCaseList();
191
                $Reporter->paintDocumentEnd();
192
        }
193

    
194
/**
195
 * Sets the params, calling this will bypass the auto parameter parsing.
196
 *
197
 * @param array $params Array of parameters for the dispatcher
198
 * @return void
199
 */
200
        public function setParams($params) {
201
                $this->params = $params;
202
                $this->_paramsParsed = true;
203
        }
204

    
205
/**
206
 * Parse URL params into a 'request'
207
 *
208
 * @return void
209
 */
210
        protected function _parseParams() {
211
                if (!$this->_paramsParsed) {
212
                        if (!isset($_SERVER['SERVER_NAME'])) {
213
                                $_SERVER['SERVER_NAME'] = '';
214
                        }
215
                        foreach ($this->params as $key => $value) {
216
                                if (isset($_GET[$key])) {
217
                                        $this->params[$key] = $_GET[$key];
218
                                }
219
                        }
220
                        if (isset($_GET['code_coverage'])) {
221
                                $this->params['codeCoverage'] = true;
222
                                $this->_checkXdebug();
223
                        }
224
                }
225
                if (empty($this->params['plugin']) && empty($this->params['core'])) {
226
                        $this->params['app'] = true;
227
                }
228
                $this->params['baseUrl'] = $this->_baseUrl;
229
                $this->params['baseDir'] = $this->_baseDir;
230
        }
231

    
232
/**
233
 * Runs a test case file.
234
 *
235
 * @return void
236
 */
237
        protected function _runTestCase() {
238
                $commandArgs = array(
239
                        'case' => $this->params['case'],
240
                        'core' => $this->params['core'],
241
                        'app' => $this->params['app'],
242
                        'plugin' => $this->params['plugin'],
243
                        'codeCoverage' => $this->params['codeCoverage'],
244
                        'showPasses' => !empty($this->params['show_passes']),
245
                        'baseUrl' => $this->_baseUrl,
246
                        'baseDir' => $this->_baseDir,
247
                );
248

    
249
                $options = array(
250
                        '--filter', $this->params['filter'],
251
                        '--output', $this->params['output'],
252
                        '--fixture', $this->params['fixture']
253
                );
254
                restore_error_handler();
255

    
256
                try {
257
                        static::time();
258
                        $command = new CakeTestSuiteCommand('CakeTestLoader', $commandArgs);
259
                        $command->run($options);
260
                } catch (MissingConnectionException $exception) {
261
                        ob_end_clean();
262
                        $baseDir = $this->_baseDir;
263
                        include CAKE . 'TestSuite' . DS . 'templates' . DS . 'missing_connection.php';
264
                        exit();
265
                }
266
        }
267

    
268
/**
269
 * Sets a static timestamp
270
 *
271
 * @param bool $reset to set new static timestamp.
272
 * @return int timestamp
273
 */
274
        public static function time($reset = false) {
275
                static $now;
276
                if ($reset || !$now) {
277
                        $now = time();
278
                }
279
                return $now;
280
        }
281

    
282
/**
283
 * Returns formatted date string using static time
284
 * This method is being used as formatter for created, modified and updated fields in Model::save()
285
 *
286
 * @param string $format format to be used.
287
 * @return string formatted date
288
 */
289
        public static function date($format) {
290
                return date($format, static::time());
291
        }
292

    
293
}