source: hadoop-register/etc/phpMailer/test/phpunit.php

Last change on this file was 57, checked in by jazz, 16 years ago
  • 第一版 Hadoop 叢集之帳號申請網頁 by Wade
File size: 10.6 KB
Line 
1<?php
2//
3// PHP framework for testing, based on the design of "JUnit".
4//
5// Written by Fred Yankowski <fred@ontosys.com>
6//            OntoSys, Inc  <http://www.OntoSys.com>
7//
8// $Id: phpunit.php,v 1.1 2002/03/30 19:32:17 bmatzelle Exp $
9
10// Copyright (c) 2000 Fred Yankowski
11
12// Permission is hereby granted, free of charge, to any person
13// obtaining a copy of this software and associated documentation
14// files (the "Software"), to deal in the Software without
15// restriction, including without limitation the rights to use, copy,
16// modify, merge, publish, distribute, sublicense, and/or sell copies
17// of the Software, and to permit persons to whom the Software is
18// furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be
21// included in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30// SOFTWARE.
31//
32error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE |
33    E_CORE_ERROR | E_CORE_WARNING);
34
35/*
36interface Test {
37  function run(&$aTestResult);
38  function countTestCases();
39}
40*/
41
42function trace($msg) {
43  return;
44  print($msg);
45  flush();
46}
47
48
49class phpUnitException {
50    /* Emulate a Java exception, sort of... */
51  var $message;
52  var $type;
53  function phpUnitException($message, $type = 'FAILURE') {
54    $this->message = $message;
55    $this->type = $type;
56  }
57  function getMessage() {
58    return $this->message;
59  }
60}
61
62class Assert {
63  function assert($boolean, $message=0) {
64    if (! $boolean)
65      $this->fail($message);
66  }
67
68  function assertEquals($expected, $actual, $message=0) {
69    if ($expected != $actual) {
70      $this->failNotEquals($expected, $actual, "expected", $message);
71    }
72  }
73
74  function assertRegexp($regexp, $actual, $message=false) {
75    if (! preg_match($regexp, $actual)) {
76      $this->failNotEquals($regexp, $actual, "pattern", $message);
77    }
78  }
79
80  function failNotEquals($expected, $actual, $expected_label, $message=0) {
81    // Private function for reporting failure to match.
82    $str = $message ? ($message . ' ') : '';
83    $str .= "($expected_label/actual)<br>";
84    $htmlExpected = htmlspecialchars($expected);
85    $htmlActual = htmlspecialchars($actual);
86    $str .= sprintf("<pre>%s\n--------\n%s</pre>",
87        $htmlExpected, $htmlActual);
88    $this->fail($str);
89  }
90}
91
92class TestCase extends Assert /* implements Test */ {
93  /* Defines context for running tests.  Specific context -- such as
94     instance variables, global variables, global state -- is defined
95     by creating a subclass that specializes the setUp() and
96     tearDown() methods.  A specific test is defined by a subclass
97     that specializes the runTest() method. */
98  var $fName;
99  var $fResult;
100  var $fExceptions = array();
101
102  function TestCase($name) {
103    $this->fName = $name;
104  }
105
106  function run($testResult=0) {
107    /* Run this single test, by calling the run() method of the
108       TestResult object which will in turn call the runBare() method
109       of this object.  That complication allows the TestResult object
110       to do various kinds of progress reporting as it invokes each
111       test.  Create/obtain a TestResult object if none was passed in.
112       Note that if a TestResult object was passed in, it must be by
113       reference. */
114    if (! $testResult)
115      $testResult = $this->_createResult();
116    $this->fResult = $testResult;
117    $testResult->run(&$this);
118    $this->fResult = 0;
119    return $testResult;
120  }
121
122  function countTestCases() {
123    return 1;
124  }
125
126  function runTest() {
127    $name = $this->name();
128    // Since isset($this->$name) is false, no way to run defensive checks
129    $this->$name();
130  }
131
132  function setUp() /* expect override */ {
133    //print("TestCase::setUp()<br>\n");
134  }
135
136  function tearDown() /* possible override */ {
137    //print("TestCase::tearDown()<br>\n");
138  }
139
140  ////////////////////////////////////////////////////////////////
141
142
143  function _createResult() /* protected */ {
144    /* override this to use specialized subclass of TestResult */
145    return new TestResult;
146  }
147
148  function fail($message=0) {
149    //printf("TestCase::fail(%s)<br>\n", ($message) ? $message : '');
150    /* JUnit throws AssertionFailedError here.  We just record the
151       failure and carry on */
152    $this->fExceptions[] = new Exception(&$message);
153  }
154
155  function error($message) {
156    /* report error that requires correction in the test script
157       itself, or (heaven forbid) in this testing infrastructure */
158    printf('<b>ERROR: ' . $message . '</b><br>');
159    $this->fResult->stop();
160  }
161
162  function failed() {
163    return count($this->fExceptions);
164  }
165
166  function getExceptions() {
167    return $this->fExceptions;
168  }
169
170  function name() {
171    return $this->fName;
172  }
173
174  function runBare() {
175    $this->setup();
176    $this->runTest();
177    $this->tearDown();
178  }
179}
180
181
182class TestSuite /* implements Test */ {
183  /* Compose a set of Tests (instances of TestCase or TestSuite), and
184     run them all. */
185  var $fTests = array();
186
187  function TestSuite($classname=false) {
188    if ($classname) {
189      // Find all methods of the given class whose name starts with
190      // "test" and add them to the test suite.  We are just _barely_
191      // able to do this with PHP's limited introspection...  Note
192      // that PHP seems to store method names in lower case, and we
193      // have to avoid the constructor function for the TestCase class
194      // superclass.  This will fail when $classname starts with
195      // "Test" since that will have a constructor method that will
196      // get matched below and then treated (incorrectly) as a test
197      // method.  So don't name any TestCase subclasses as "Test..."!
198      if (floor(phpversion()) >= 4) {
199  // PHP4 introspection, submitted by Dylan Kuhn
200  $names = get_class_methods($classname);
201  while (list($key, $method) = each($names)) {
202    if (preg_match('/^test/', $method) && $method != "testcase") {
203      $this->addTest(new $classname($method));
204    }
205  }
206      }
207      else {
208  $dummy = new $classname("dummy");
209  $names = (array) $dummy;
210  while (list($key, $value) = each($names)) {
211    $type = gettype($value);
212    if ($type == "user function" && preg_match('/^test/', $key)
213    && $key != "testcase") {
214      $this->addTest(new $classname($key));
215    }
216  }
217      }
218    }
219  }
220
221  function addTest($test) {
222    /* Add TestCase or TestSuite to this TestSuite */
223    $this->fTests[] = $test;
224  }
225
226  function run(&$testResult) {
227    /* Run all TestCases and TestSuites comprising this TestSuite,
228       accumulating results in the given TestResult object. */
229    reset($this->fTests);
230    while (list($na, $test) = each($this->fTests)) {
231      if ($testResult->shouldStop())
232  break;
233      $test->run(&$testResult);
234    }
235  }
236
237  function countTestCases() {
238    /* Number of TestCases comprising this TestSuite (including those
239       in any constituent TestSuites) */
240    $count = 0;
241    reset($fTests);
242    while (list($na, $test_case) = each($this->fTests)) {
243      $count += $test_case->countTestCases();
244    }
245    return $count;
246  }
247}
248
249
250class TestFailure {
251  /* Record failure of a single TestCase, associating it with the
252     exception(s) that occurred */
253  var $fFailedTestName;
254  var $fExceptions;
255
256  function TestFailure(&$test, &$exceptions) {
257    $this->fFailedTestName = $test->name();
258    $this->fExceptions = $exceptions;
259  }
260
261  function getExceptions() {
262      return $this->fExceptions;
263  }
264  function getTestName() {
265    return $this->fFailedTestName;
266  }
267}
268
269
270class TestResult {
271  /* Collect the results of running a set of TestCases. */
272  var $fFailures = array();
273  var $fRunTests = 0;
274  var $fStop = false;
275
276  function TestResult() { }
277
278  function _endTest($test) /* protected */ {
279      /* specialize this for end-of-test action, such as progress
280   reports  */
281  }
282
283  function getFailures() {
284    return $this->fFailures;
285  }
286
287  function run($test) {
288    /* Run a single TestCase in the context of this TestResult */
289    $this->_startTest($test);
290    $this->fRunTests++;
291
292    $test->runBare();
293
294    /* this is where JUnit would catch AssertionFailedError */
295    $exceptions = $test->getExceptions();
296    if ($exceptions)
297      $this->fFailures[] = new TestFailure(&$test, &$exceptions);
298    $this->_endTest($test);
299  }
300
301  function countTests() {
302    return $this->fRunTests;
303  }
304
305  function shouldStop() {
306    return $this->fStop;
307  }
308
309  function _startTest($test) /* protected */ {
310      /* specialize this for start-of-test actions */
311  }
312
313  function stop() {
314    /* set indication that the test sequence should halt */
315    $fStop = true;
316  }
317
318  function countFailures() {
319    return count($this->fFailures);
320  }
321}
322
323
324class TextTestResult extends TestResult {
325  /* Specialize TestResult to produce text/html report */
326  function TextTestResult() {
327    $this->TestResult();  // call superclass constructor
328  }
329
330  function report() {
331    /* report result of test run */
332    $nRun = $this->countTests();
333    $nFailures = $this->countFailures();
334    printf("<p>%s test%s run<br>", $nRun, ($nRun == 1) ? '' : 's');
335    printf("%s failure%s.<br>\n", $nFailures, ($nFailures == 1) ? '' : 's');
336    if ($nFailures == 0)
337      return;
338
339    print("<ol>\n");
340    $failures = $this->getFailures();
341    while (list($i, $failure) = each($failures)) {
342      $failedTestName = $failure->getTestName();
343      printf("<li>%s\n", $failedTestName);
344
345      $exceptions = $failure->getExceptions();
346      print("<ul>");
347      while (list($na, $exception) = each($exceptions))
348  printf("<li>%s\n", $exception->getMessage());
349      print("</ul>");
350    }
351    print("</ol>\n");
352  }
353
354  function _startTest($test) {
355    printf("%s ", $test->name());
356    flush();
357  }
358
359  function _endTest($test) {
360    $outcome = $test->failed()
361       ? "<font color=\"red\">FAIL</font>"
362       : "<font color=\"green\">ok</font>";
363    printf("$outcome<br>\n");
364    flush();
365  }
366}
367
368
369class TestRunner {
370  /* Run a suite of tests and report results. */
371  function run($suite) {
372    $result = new TextTestResult;
373    $suite->run($result);
374    $result->report();
375  }
376}
377
378?>
Note: See TracBrowser for help on using the repository browser.