Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
 
4
/**
5
 * PHP Version 4
6
 *
7
 * Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 *
14
 *   * Redistributions of source code must retain the above copyright
15
 *     notice, this list of conditions and the following disclaimer.
16
 *
17
 *   * Redistributions in binary form must reproduce the above copyright
18
 *     notice, this list of conditions and the following disclaimer in
19
 *     the documentation and/or other materials provided with the
20
 *     distribution.
21
 *
22
 *   * Neither the name of Sebastian Bergmann nor the names of his
23
 *     contributors may be used to endorse or promote products derived
24
 *     from this software without specific prior written permission.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
35
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37
 * POSSIBILITY OF SUCH DAMAGE.
38
 *
39
 * @category   Testing
40
 * @package    PHPUnit
41
 * @author     Scott Mattocks <scott@crisscott.com>
42
 * @copyright  2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
43
 * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
44
 * @version    CVS: $Id: Skeleton.php,v 1.8 2005/11/10 09:47:14 sebastian Exp $
45
 * @link       http://pear.php.net/package/PHPUnit
46
 * @since      File available since Release 1.1.0
47
 */
48
 
49
/**
50
 * Class for creating a PHPUnit_TestCase skeleton file.
51
 *
52
 * This class will take a classname as a parameter on construction and will
53
 * create a PHP file that contains the skeleton of a PHPUnit_TestCase
54
 * subclass. The test case will contain a test foreach method of the class.
55
 * Methods of the parent class will, by default, be excluded from the test
56
 * class. Passing and optional construction parameter will include them.
57
 *
58
 * Example
59
 *
60
 *   <?php
61
 *   require_once 'PHPUnit/Skeleton.php';
62
 *   $ps = new PHPUnit_Skeleton('PHPUnit_Skeleton', 'PHPUnit/Skeleton.php');
63
 *
64
 *   // Generate the test class.
65
 *   // Default settings will not include any parent class methods, but
66
 *   // will include private methods.
67
 *   $ps->createTestClass();
68
 *
69
 *   // Write the new test class to file.
70
 *   // By default, code to run the test will be included.
71
 *   $ps->writeTestClass();
72
 *   ?>
73
 *
74
 * Now open the skeleton class and fill in the details.
75
 * If you run the test as is, all tests will fail and
76
 * you will see plenty of undefined constant errors.
77
 *
78
 * @category   Testing
79
 * @package    PHPUnit
80
 * @author     Scott Mattocks <scott@crisscott.com>
81
 * @copyright  2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
82
 * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
83
 * @version    Release: 1.3.2
84
 * @link       http://pear.php.net/package/PHPUnit
85
 * @since      Class available since Release 1.1.0
86
 */
87
class PHPUnit_Skeleton {
88
    /**
89
     * Path to the class file to create a skeleton for.
90
     * @var string
91
     */
92
    var $classPath;
93
 
94
    /**
95
     * The name of the class
96
     * @var string
97
     */
98
    var $className;
99
 
100
    /**
101
     * Path to the configuration file needed by class to test.
102
     * @var string
103
     */
104
    var $configFile;
105
 
106
    /**
107
     * Whether or not to include the methods of the parent class when testing.
108
     * @var boolean
109
     */
110
    var $includeParents;
111
 
112
    /**
113
     * Whether or not to test private methods.
114
     * @var boolean
115
     */
116
    var $includePrivate;
117
 
118
    /**
119
     * The test class that will be created.
120
     * @var string
121
     */
122
    var $testClass;
123
 
124
    /**
125
     * Constructor. Sets the class members and check that the class
126
     * to test is accessible.
127
     *
128
     * @access public
129
     * @param  string  $className
130
     * @param  string  $classPath
131
     * @param  boolean $includeParents Wheter to include the parent's methods in the test.
132
     * @return void
133
     */
134
    function PHPUnit_Skeleton($className, $classPath, $includeParents = FALSE, $includePrivate = TRUE) {
135
        // Set up the members.
136
        if (@is_readable($classPath)) {
137
            $this->className = $className;
138
            $this->classPath = $classPath;
139
        } else {
140
            $this->_handleErrors($classPath . ' is not readable. Cannot create test class.');
141
        }
142
 
143
        // Do we want to include parent methods?
144
        $this->includeParents = $includeParents;
145
 
146
        // Do we want to allow private methods?
147
        $this->includePrivate = $includePrivate;
148
    }
149
 
150
    /**
151
     * The class to test may require a special config file before it can be
152
     * instantiated. This method lets you set that file.
153
     *
154
     * @access public
155
     * @param  string $configPath
156
     * @return void
157
     */
158
    function setConfigFile($configFile) {
159
        // Check that the file is readable
160
        if (@is_readable($configFile)) {
161
            $this->configFile = $configFile;
162
        } else {
163
            $this->_handleErrors($configFile . ' is not readable. Cannot create test class.');
164
        }
165
    }
166
 
167
    /**
168
     * Create the code that will be the skeleton of the test case.
169
     *
170
     * The test case must have a clss definition, one var, a constructor
171
     * setUp, tearDown, and methods. Optionally and by default the code
172
     * to run the test is added when the class is written to file.
173
     *
174
     * @access public
175
     * @param  none
176
     * @return void
177
     */
178
    function createTestClass() {
179
        // Instantiate the object.
180
        if (isset($this->configFile)) {
181
            require_once $this->configFile;
182
        }
183
 
184
        require_once $this->classPath;
185
 
186
        // Get the methods.
187
        $classMethods = get_class_methods($this->className);
188
 
189
        // Remove the parent methods if needed.
190
        if (!$this->includeParents) {
191
            $parentMethods = get_class_methods(get_parent_class($this->className));
192
 
193
            if (count($parentMethods)) {
194
                $classMethods = array_diff($classMethods, $parentMethods);
195
            }
196
        }
197
 
198
        // Create the class definition, constructor, setUp and tearDown.
199
        $this->_createDefinition();
200
        $this->_createConstructor();
201
        $this->_createSetUpTearDown();
202
 
203
        if (count($classMethods)) {
204
            // Foreach method create a test case.
205
            foreach ($classMethods as $method) {
206
                // Unless it is the constructor.
207
                if (strcasecmp($this->className, $method) !== 0) {
208
                  // Check for private methods.
209
                  if (!$this->includePrivate && strpos($method, '_') === 0) {
210
                      continue;
211
                  } else {
212
                      $this->_createMethod($method);
213
                  }
214
                }
215
            }
216
        }
217
 
218
        // Finis off the class.
219
        $this->_finishClass();
220
    }
221
 
222
    /**
223
     * Create the class definition.
224
     *
225
     * The definition consist of a header comment, require statment
226
     * for getting the PHPUnit file, the actual class definition,
227
     * and the definition of the class member variable.
228
     *
229
     * All of the code needed for the new class is stored in the
230
     * testClass member.
231
     *
232
     * @access private
233
     * @param  none
234
     * @return void
235
     */
236
    function _createDefinition() {
237
        // Create header comment.
238
        $this->testClass =
239
          "/**\n" .
240
          " * PHPUnit test case for " . $this->className . "\n" .
241
          " * \n" .
242
          " * The method skeletons below need to be filled in with \n" .
243
          " * real data so that the tests will run correctly. Replace \n" .
244
          " * all EXPECTED_VAL and PARAM strings with real data. \n" .
245
          " * \n" .
246
          " * Created with PHPUnit_Skeleton on " . date('Y-m-d') . "\n" .
247
          " */\n";
248
 
249
        // Add the require statements.
250
        $this->testClass .= "require_once 'PHPUnit.php';\n";
251
 
252
        // Add the class definition and variable definition.
253
        $this->testClass .=
254
          "class " . $this->className . "Test extends PHPUnit_TestCase {\n\n" .
255
          "    var \$" . $this->className . ";\n\n";
256
    }
257
 
258
    /**
259
     * Create the class constructor. (PHP4 style)
260
     *
261
     * The constructor simply calls the PHPUnit_TestCase method.
262
     * This code is taken from the PHPUnit documentation.
263
     *
264
     * All of the code needed for the new class is stored in the
265
     * testClass member.
266
     *
267
     * @access private
268
     * @param  none
269
     * @return void
270
     */
271
    function _createConstructor() {
272
        // Create the test class constructor.
273
        $this->testClass.=
274
          "    function " . $this->className . "Test(\$name)\n" .
275
          "    {\n" .
276
          "        \$this->PHPUnit_TestCase(\$name);\n" .
277
          "    }\n\n";
278
    }
279
 
280
    /**
281
     * Create setUp and tearDown methods.
282
     *
283
     * The setUp method creates the instance of the object to test.
284
     * The tearDown method releases the instance.
285
     * This code is taken from the PHPUnit documentation.
286
     *
287
     * All of the code needed for the new class is stored in the
288
     * testClass member.
289
     *
290
     * @access private
291
     * @param  none
292
     * @return void
293
     */
294
    function _createSetUpTearDown() {
295
        // Create the setUp method.
296
        $this->testClass .=
297
          "    function setUp()\n" .
298
          "    {\n";
299
 
300
        if (isset($this->configFile)) {
301
            $this->testClass .=
302
            "        require_once '" . $this->configFile . "';\n";
303
        }
304
 
305
        $this->testClass .=
306
          "        require_once '" . $this->classPath . "';\n" .
307
          "        \$this->" . $this->className . " =& new " . $this->className . "(PARAM);\n" .
308
          "    }\n\n";
309
 
310
        // Create the tearDown method.
311
        $this->testClass .=
312
          "    function tearDown()\n" .
313
          "    {\n" .
314
          "        unset(\$this->" . $this->className . ");\n" .
315
          "    }\n\n";
316
    }
317
 
318
    /**
319
     * Create a basic skeleton for test methods.
320
     *
321
     * This code is taken from the PHPUnit documentation.
322
     *
323
     * All of the code needed for the new class is stored in the
324
     * testClass member.
325
     *
326
     * @access private
327
     * @param  none
328
     * @return void
329
     */
330
    function _createMethod($methodName) {
331
        // Create a test method.
332
        $this->testClass .=
333
          "    function test" . $methodName . "()\n" .
334
          "    {\n" .
335
          "        \$result   = \$this->" . $this->className . "->" . $methodName . "(PARAM);\n" .
336
          "        \$expected = EXPECTED_VAL;\n" .
337
          "        \$this->assertEquals(\$expected, \$result);\n" .
338
          "    }\n\n";
339
    }
340
 
341
    /**
342
     * Add the closing brace needed for a proper class definition.
343
     *
344
     * All of the code needed for the new class is stored in the
345
     * testClass member.
346
     *
347
     * @access private
348
     * @param  none
349
     * @return void
350
     */
351
    function _finishClass() {
352
        // Close off the class.
353
        $this->testClass.= "}\n";
354
    }
355
 
356
    /**
357
     * Create the code that will actually run the test.
358
     *
359
     * This code is added by default so that the test can be run
360
     * just by running the file. To have it not added pass false
361
     * as the second parameter to the writeTestClass method.
362
     * This code is taken from the PHPUnit documentation.
363
     *
364
     * All of the code needed for the new class is stored in the
365
     * testClass member.
366
     *
367
     * @access private
368
     * @param  none
369
     * @return void
370
     */
371
    function _createTest() {
372
        // Create a call to the test.
373
        $test =
374
          "// Running the test.\n" .
375
          "\$suite  = new PHPUnit_TestSuite('" . $this->className . "Test');\n" .
376
          "\$result = PHPUnit::run(\$suite);\n" .
377
          "echo \$result->toString();\n";
378
 
379
        return $test;
380
    }
381
 
382
    /**
383
     * Write the test class to file.
384
     *
385
     * This will write the test class created using the createTestClass
386
     * method to a file called <className>Test.php. By default the file
387
     * is written to the current directory and will have code to run
388
     * the test appended to the bottom of the file.
389
     *
390
     * @access public
391
     * @param  string  $destination The directory to write the file to.
392
     * @param  boolean $addTest     Wheter to add the test running code.
393
     * @return void
394
     */
395
    function writeTestClass($destination = './', $addTest = TRUE) {
396
        // Check for something to write to file.
397
        if (!isset($this->testClass)) {
398
            $this->_handleErrors('Noting to write.', PHPUS_WARNING);
399
            return;
400
        }
401
 
402
        // Open the destination file.
403
        $fp = fopen($destination . $this->className . 'Test.php', 'w');
404
        fwrite($fp, "<?php\n");
405
 
406
        // Write the test class.
407
        fwrite($fp, $this->testClass);
408
 
409
        // Add the call to test the class in the file if we were asked to.
410
        if ($addTest) {
411
            fwrite($fp, $this->_createTest());
412
        }
413
 
414
        // Close the file.
415
        fwrite($fp, "?>\n");
416
        fclose($fp);
417
    }
418
 
419
    /**
420
     * Error handler.
421
     *
422
     * This method should be rewritten to use the prefered error
423
     * handling method. (PEAR_ErrorStack)
424
     *
425
     * @access private
426
     * @param  string  $message The error message.
427
     * @param  integer $type    An indication of the severity of the error.
428
     * @return void             Code may cause PHP to exit.
429
     */
430
    function _handleErrors($message, $type = E_USER_ERROR) {
431
        // For now just echo the message.
432
        echo $message;
433
 
434
        // Check to see if we should quit.
435
        if ($type == E_USER_ERROR) {
436
            exit;
437
        }
438
    }
439
}
440
 
441
/*
442
 * Local variables:
443
 * tab-width: 4
444
 * c-basic-offset: 4
445
 * c-hanging-comment-ender-p: nil
446
 * End:
447
 */
448
?>