Хранилища Subversion ant

Редакция

Содержимое файла | Последнее изменение | Открыть журнал | RSS

Редакция Автор № строки Строка
69 alex-w 1
<?php
2
/**
3
 * PEAR_Command_Test (run-tests)
4
 *
5
 * PHP versions 4 and 5
6
 *
7
 * LICENSE: This source file is subject to version 3.0 of the PHP license
8
 * that is available through the world-wide-web at the following URI:
9
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
10
 * the PHP License and are unable to obtain it through the web, please
11
 * send a note to license@php.net so we can mail you a copy immediately.
12
 *
13
 * @category   pear
14
 * @package    PEAR
15
 * @author     Stig Bakken <ssb@php.net>
16
 * @author     Martin Jansen <mj@php.net>
17
 * @author     Greg Beaver <cellog@php.net>
18
 * @copyright  1997-2008 The PHP Group
19
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
20
 * @version    CVS: $Id: Test.php,v 1.27 2008/01/03 20:26:36 cellog Exp $
21
 * @link       http://pear.php.net/package/PEAR
22
 * @since      File available since Release 0.1
23
 */
24
 
25
/**
26
 * base class
27
 */
28
require_once 'PEAR/Command/Common.php';
29
 
30
/**
31
 * PEAR commands for login/logout
32
 *
33
 * @category   pear
34
 * @package    PEAR
35
 * @author     Stig Bakken <ssb@php.net>
36
 * @author     Martin Jansen <mj@php.net>
37
 * @author     Greg Beaver <cellog@php.net>
38
 * @copyright  1997-2008 The PHP Group
39
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
40
 * @version    Release: 1.7.2
41
 * @link       http://pear.php.net/package/PEAR
42
 * @since      Class available since Release 0.1
43
 */
44
 
45
class PEAR_Command_Test extends PEAR_Command_Common
46
{
47
    // {{{ properties
48
 
49
    var $commands = array(
50
        'run-tests' => array(
51
            'summary' => 'Run Regression Tests',
52
            'function' => 'doRunTests',
53
            'shortcut' => 'rt',
54
            'options' => array(
55
                'recur' => array(
56
                    'shortopt' => 'r',
57
                    'doc' => 'Run tests in child directories, recursively.  4 dirs deep maximum',
58
                ),
59
                'ini' => array(
60
                    'shortopt' => 'i',
61
                    'doc' => 'actual string of settings to pass to php in format " -d setting=blah"',
62
                    'arg' => 'SETTINGS'
63
                ),
64
                'realtimelog' => array(
65
                    'shortopt' => 'l',
66
                    'doc' => 'Log test runs/results as they are run',
67
                ),
68
                'quiet' => array(
69
                    'shortopt' => 'q',
70
                    'doc' => 'Only display detail for failed tests',
71
                ),
72
                'simple' => array(
73
                    'shortopt' => 's',
74
                    'doc' => 'Display simple output for all tests',
75
                ),
76
                'package' => array(
77
                    'shortopt' => 'p',
78
                    'doc' => 'Treat parameters as installed packages from which to run tests',
79
                ),
80
                'phpunit' => array(
81
                    'shortopt' => 'u',
82
                    'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests
83
If none is found, all .phpt tests will be tried instead.',
84
                ),
85
                'tapoutput' => array(
86
                    'shortopt' => 't',
87
                    'doc' => 'Output run-tests.log in TAP-compliant format',
88
                ),
89
                'cgi' => array(
90
                    'shortopt' => 'c',
91
                    'doc' => 'CGI php executable (needed for tests with POST/GET section)',
92
                    'arg' => 'PHPCGI',
93
                ),
94
                'coverage' => array(
95
                    'shortopt' => 'x',
96
                    'doc'      => 'Generate a code coverage report (requires Xdebug 2.0.0+)',
97
                ),
98
            ),
99
            'doc' => '[testfile|dir ...]
100
Run regression tests with PHP\'s regression testing script (run-tests.php).',
101
            ),
102
        );
103
 
104
    var $output;
105
 
106
    // }}}
107
    // {{{ constructor
108
 
109
    /**
110
     * PEAR_Command_Test constructor.
111
     *
112
     * @access public
113
     */
114
    function PEAR_Command_Test(&$ui, &$config)
115
    {
116
        parent::PEAR_Command_Common($ui, $config);
117
    }
118
 
119
    // }}}
120
    // {{{ doRunTests()
121
 
122
    function doRunTests($command, $options, $params)
123
    {
124
        if (isset($options['phpunit']) && isset($options['tapoutput'])) {
125
            return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time');
126
        }
127
        require_once 'PEAR/Common.php';
128
        require_once 'System.php';
129
        $log = new PEAR_Common;
130
        $log->ui = &$this->ui; // slightly hacky, but it will work
131
        $tests = array();
132
        $depth = isset($options['recur']) ? 4 : 1;
133
 
134
        if (!count($params)) {
135
            $params[] = '.';
136
        }
137
        if (isset($options['package'])) {
138
            $oldparams = $params;
139
            $params = array();
140
            $reg = &$this->config->getRegistry();
141
            foreach ($oldparams as $param) {
142
                $pname = $reg->parsePackageName($param, $this->config->get('default_channel'));
143
                if (PEAR::isError($pname)) {
144
                    return $this->raiseError($pname);
145
                }
146
 
147
                $package = &$reg->getPackage($pname['package'], $pname['channel']);
148
                if (!$package) {
149
                    return PEAR::raiseError('Unknown package "' .
150
                        $reg->parsedPackageNameToString($pname) . '"');
151
                }
152
 
153
                $filelist = $package->getFilelist();
154
                foreach ($filelist as $name => $atts) {
155
                    if (isset($atts['role']) && $atts['role'] != 'test') {
156
                        continue;
157
                    }
158
 
159
                    if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) {
160
                        $params[] = $atts['installed_as'];
161
                        continue;
162
                    } elseif (!preg_match('/\.phpt\\z/', $name)) {
163
                        continue;
164
                    }
165
                    $params[] = $atts['installed_as'];
166
                }
167
            }
168
        }
169
 
170
        foreach ($params as $p) {
171
            if (is_dir($p)) {
172
                if (isset($options['phpunit'])) {
173
                    $dir = System::find(array($p, '-type', 'f',
174
                                                '-maxdepth', $depth,
175
                                                '-name', 'AllTests.php'));
176
                    if (count($dir)) {
177
                        foreach ($dir as $p) {
178
                            $p = realpath($p);
179
                            if (!count($tests) ||
180
                                  (count($tests) && strlen($p) < strlen($tests[0]))) {
181
                                // this is in a higher-level directory, use this one instead.
182
                                $tests = array($p);
183
                            }
184
                        }
185
                    }
186
                    continue;
187
                }
188
                $dir = System::find(array($p, '-type', 'f',
189
                                            '-maxdepth', $depth,
190
                                            '-name', '*.phpt'));
191
                $tests = array_merge($tests, $dir);
192
            } else {
193
                if (isset($options['phpunit'])) {
194
                    if (preg_match('/AllTests\.php\\z/i', $p)) {
195
                        $p = realpath($p);
196
                        if (!count($tests) ||
197
                              (count($tests) && strlen($p) < strlen($tests[0]))) {
198
                            // this is in a higher-level directory, use this one instead.
199
                            $tests = array($p);
200
                        }
201
                    }
202
                    continue;
203
                }
204
 
205
                if (file_exists($p) && preg_match('/\.phpt$/', $p)) {
206
                    $tests[] = $p;
207
                    continue;
208
                }
209
 
210
                if (!preg_match('/\.phpt\\z/', $p)) {
211
                    $p .= '.phpt';
212
                }
213
                $dir = System::find(array(dirname($p), '-type', 'f',
214
                                            '-maxdepth', $depth,
215
                                            '-name', $p));
216
                $tests = array_merge($tests, $dir);
217
            }
218
        }
219
 
220
        $ini_settings = '';
221
        if (isset($options['ini'])) {
222
            $ini_settings .= $options['ini'];
223
        }
224
 
225
        if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) {
226
            $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}";
227
        }
228
 
229
        if ($ini_settings) {
230
            $this->ui->outputData('Using INI settings: "' . $ini_settings . '"');
231
        }
232
        $skipped = $passed = $failed = array();
233
        $tests_count = count($tests);
234
        $this->ui->outputData('Running ' . $tests_count . ' tests', $command);
235
        $start = time();
236
        if (isset($options['realtimelog']) && file_exists('run-tests.log')) {
237
            unlink('run-tests.log');
238
        }
239
 
240
        if (isset($options['tapoutput'])) {
241
            $tap = '1..' . $tests_count . "\n";
242
        }
243
 
244
        require_once 'PEAR/RunTest.php';
245
        $run = new PEAR_RunTest($log, $options);
246
        $run->tests_count = $tests_count;
247
 
248
        if (isset($options['coverage']) && extension_loaded('xdebug')){
249
            $run->xdebug_loaded = true;
250
        } else {
251
            $run->xdebug_loaded = false;
252
        }
253
 
254
        $j = $i = 1;
255
        foreach ($tests as $t) {
256
            if (isset($options['realtimelog'])) {
257
                $fp = @fopen('run-tests.log', 'a');
258
                if ($fp) {
259
                    fwrite($fp, "Running test [$i / $tests_count] $t...");
260
                    fclose($fp);
261
                }
262
            }
263
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
264
            if (isset($options['phpunit'])) {
265
                $result = $run->runPHPUnit($t, $ini_settings);
266
            } else {
267
                $result = $run->run($t, $ini_settings, $j);
268
            }
269
            PEAR::staticPopErrorHandling();
270
            if (PEAR::isError($result)) {
271
                $this->ui->log($result->getMessage());
272
                continue;
273
            }
274
 
275
            if (isset($options['tapoutput'])) {
276
                $tap .= $result[0] . ' ' . $i . $result[1] . "\n";
277
                continue;
278
            }
279
 
280
            if (isset($options['realtimelog'])) {
281
                $fp = @fopen('run-tests.log', 'a');
282
                if ($fp) {
283
                    fwrite($fp, "$result\n");
284
                    fclose($fp);
285
                }
286
            }
287
 
288
            if ($result == 'FAILED') {
289
                $failed[] = $t;
290
            }
291
            if ($result == 'PASSED') {
292
                $passed[] = $t;
293
            }
294
            if ($result == 'SKIPPED') {
295
                $skipped[] = $t;
296
            }
297
 
298
            $j++;
299
        }
300
 
301
        $total = date('i:s', time() - $start);
302
        if (isset($options['tapoutput'])) {
303
            $fp = @fopen('run-tests.log', 'w');
304
            if ($fp) {
305
                fwrite($fp, $tap, strlen($tap));
306
                fclose($fp);
307
                $this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') .
308
                    '"', $command);
309
            }
310
        } else {
311
            if (count($failed)) {
312
                $output = "TOTAL TIME: $total\n";
313
                $output .= count($passed) . " PASSED TESTS\n";
314
                $output .= count($skipped) . " SKIPPED TESTS\n";
315
                        $output .= count($failed) . " FAILED TESTS:\n";
316
                foreach ($failed as $failure) {
317
                        $output .= $failure . "\n";
318
                }
319
 
320
                $mode = isset($options['realtimelog']) ? 'a' : 'w';
321
                $fp   = @fopen('run-tests.log', $mode);
322
 
323
                if ($fp) {
324
                    fwrite($fp, $output, strlen($output));
325
                    fclose($fp);
326
                    $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command);
327
                }
328
            } elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) {
329
                @unlink('run-tests.log');
330
            }
331
        }
332
        $this->ui->outputData('TOTAL TIME: ' . $total);
333
        $this->ui->outputData(count($passed) . ' PASSED TESTS', $command);
334
        $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command);
335
        if (count($failed)) {
336
                $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command);
337
                foreach ($failed as $failure) {
338
                        $this->ui->outputData($failure, $command);
339
                }
340
        }
341
 
342
        return true;
343
    }
344
    // }}}
345
}