Location: PHPKode > projects > XMLNuke Web Development Framework XML > xmlnuke-php5-v3.5r356/xmlnuke-php5/bin/modules/phpunit/phpunit.php
<?php
//
// PHP framework for testing, based on the design of "JUnit".
//
// Written by Fred Yankowski <hide@address.com>
//            OntoSys, Inc  <http://www.OntoSys.com>
//
// $Id: phpunit.php,v 1.1 2006/02/22 20:09:39 jg Exp $

// Copyright (c) 2000 Fred Yankowski

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE |
		E_CORE_ERROR | E_CORE_WARNING);

/*
interface Test {
  function run(&$aTestResult);
  function countTestCases();
}
*/

function trace($msg) {
  return;
  print($msg);
  flush();
}

if (phpversion() >= '4') {
    function PHPUnit_error_handler($errno, $errstr, $errfile, $errline) {
	global $PHPUnit_testRunning;
	if (error_reporting())
	    $PHPUnit_testRunning[0]->fail("<B>PHP ERROR:</B> ".$errstr." <B>in</B> ".$errfile." <B>at line</B> ".$errline);
    }
}

class PHPUNITException extends Exception {
    /* Emulate a Java PHPUNITException, sort of... */
  var $message;
  var $type;
  function PHPUNITException($message, $type = 'FAILURE') {
    $this->message = $message;
    $this->type = $type;
  }
  function getType() {
    return $this->type;
  }
}

class Assert {
  function assert($boolean, $message=0) {
    if (! $boolean)
      $this->fail($message);
  }

  function assertEquals($expected, $actual, $message=0) {
      if (gettype($expected) != gettype($actual)) {
	  $this->failNotEquals($expected, $actual, "expected", $message);
	  return;
      }
      if (phpversion() < '4') {
	  if (is_object($expected) or is_object($actual)
	      or is_array($expected) or is_array($actual)) {
	      $this->error("INVALID TEST: cannot compare arrays or objects in PHP3");
	      return;
	  }
      }
      if (phpversion() >= '4' && is_object($expected)) {
	  if (get_class($expected) != get_class($actual)) {
	      $this->failNotEquals($expected, $actual, "expected", $message);
	      return;
	  }
	  if (method_exists($expected, "equals")) {
	      if (! $expected->equals($actual)) {
		  $this->failNotEquals($expected, $actual, "expected", $message);
	      }
	      return;		// no further tests after equals()

	  }
      }
      if (phpversion() >= '4.0.4') {
	  if (is_null($expected) != is_null($actual)) {
	      $this->failNotEquals($expected, $actual, "expected", $message);
	      return;
	  }
      }
      if ($expected != $actual) {
	  $this->failNotEquals($expected, $actual, "expected", $message);
      }
  }

  function assertRegexp($regexp, $actual, $message=false) {
    if (! preg_match($regexp, $actual)) {
      $this->failNotEquals($regexp, $actual, "pattern", $message);
    }
  }

  function assertEqualsMultilineStrings($string0, $string1,
  $message="") {
    $lines0 = split("\n",$string0);
    $lines1 = split("\n",$string1);
    if (sizeof($lines0) != sizeof($lines1)) {
      $this->failNotEquals(sizeof($lines0)." line(s)",
                           sizeof($lines1)." line(s)", "expected", $message);
    }
    for($i=0; $i< sizeof($lines0); $i++) {
      $this->assertEquals(trim($lines0[$i]),
                          trim($lines1[$i]),
                          "line ".($i+1)." of multiline strings differ. ".$message); 
    }
  }

  function _formatValue($value, $class="") {
      $translateValue = $value;
      if (phpversion() >= '4.0.0') {
	  if (is_object($value)) {
	      if (method_exists($value, "toString") ) {
		  $translateValue = $value->toString();
	      }
	      else {
		  $translateValue = serialize($value);
	      }
	  }
	  else if (is_array($value)) {
	      $translateValue = serialize($value);
	  }
      }
      $htmlValue = "<code class=\"$class\">"
	   . htmlspecialchars($translateValue) . "</code>";
      if (phpversion() >= '4.0.0') {
	  if (is_bool($value)) {
	      $htmlValue = $value ? "<i>true</i>" : "<i>false</i>";
	  }
	  elseif (phpversion() >= '4.0.4' && is_null($value)) {
	      $htmlValue = "<i>null</i>";
	  }
	  $htmlValue .= "&nbsp;&nbsp;&nbsp;<span class=\"typeinfo\">";
	  $htmlValue .= "type:" . gettype($value);
	  $htmlValue .= is_object($value) ? ", class:" . get_class($value) : "";
	  $htmlValue .= "</span>";
      }
      return $htmlValue;
  }

  function failNotEquals($expected, $actual, $expected_label, $message=0) {
    // Private function for reporting failure to match.
    $str = $message ? ($message . ' ') : '';
    //$str .= "($expected_label/actual)<br>";
    $str .= "<br>";
    $str .= sprintf("%s<br>%s",
		    $this->_formatValue($expected, "expected"),
		    $this->_formatValue($actual, "actual"));
    $this->fail($str);
  }
}

class TestCase extends Assert /* implements Test */ {
  /* Defines context for running tests.  Specific context -- such as
     instance variables, global variables, global state -- is defined
     by creating a subclass that specializes the setUp() and
     tearDown() methods.  A specific test is defined by a subclass
     that specializes the runTest() method. */
  var $fName;
  var $fClassName;
  var $fResult;
  var $fPHPUNITExceptions = array();

  function TestCase($name) {
    $this->fName = $name;
  }

  function run(&$testResult) {
    /*
     * Formerly, this function's parameter was a value with a default
     * argument of 0.  In recent versions of PHP 4, call-time
     * reference-passing is deprecated (enable
     * allow_call_time_pass_reference in php.ini if you wish to allow
     * it), so if run must take a reference, that fact must be specified
     * in the function declaration.  As a result of this change, run may
     * no longer have a default argument (defaults make no sense w.r.t.
     * references).
     */
    $this->fResult = $testResult;
    $testResult->run($this);
    $this->fResult = 0;
    return $testResult;
  }
  
  function classname() {
	  if (isset($this->fClassName)) {
		return $this->fClassName;
	  } else {
		return get_class($this);
	  }
  }

  function countTestCases() {
    return 1;
  }

  function runTest() {
    if (phpversion() >= '4') {
	global $PHPUnit_testRunning;
	eval('$PHPUnit_testRunning[0] = & $this;');
	// Saved ref to current TestCase, so that the error handler
	// can access it.  This code won't even parse in PHP3, so we
	// hide it in an eval.

	$old_handler = set_error_handler("PHPUnit_error_handler");
	// errors will now be handled by our error handler
      }

      $name = $this->name();
      if (phpversion() >= '4' && ! method_exists($this, $name)) {
          $this->error("Method '$name' does not exist");
      }
      else
          $this->$name();

      if (phpversion() >= '4') {
          if ($old_handler)
	      set_error_handler($old_handler); // revert to prior error handler
	  $PHPUnit_testRunning = null;
      }
  }

  function setUp() /* expect override */ {
    //print("TestCase::setUp()<br>\n");
  }

  function tearDown() /* possible override */ {
    //print("TestCase::tearDown()<br>\n");
  }

  ////////////////////////////////////////////////////////////////

  function fail($message=0) {
    //printf("TestCase::fail(%s)<br>\n", ($message) ? $message : '');
    /* JUnit throws AssertionFailedError here.  We just record the
       failure and carry on */
    $this->fPHPUNITExceptions[] = new PHPUNITException($message, 'FAILURE');
  }

  function error($message) {
    /* report error that requires correction in the test script
       itself, or (heaven forbid) in this testing infrastructure */
    $this->fPHPUNITExceptions[] = new PHPUNITException($message, 'ERROR');
    $this->fResult->stop();	// [does not work]
  }

  function failed() {
      reset($this->fPHPUNITExceptions);
      while (list($key, $PHPUNITException) = each($this->fPHPUNITExceptions)) {
	  if ($PHPUNITException->type == 'FAILURE')
	      return true;
      }
      return false;
  }
  function errored() {
      reset($this->fPHPUNITExceptions);
      while (list($key, $PHPUNITException) = each($this->fPHPUNITExceptions)) {
	  if ($PHPUNITException->type == 'ERROR')
	      return true;
      }
      return false;
  }

  function getPHPUNITExceptions() {
    return $this->fPHPUNITExceptions;
  }

  function name() {
    return $this->fName;
  }

  function runBare() {
    $this->setup();
    $this->runTest();
    $this->tearDown();
  }
}


class TestSuite /* implements Test */ {
  /* Compose a set of Tests (instances of TestCase or TestSuite), and
     run them all. */
  var $fTests = array();
  var $fClassname;

  function TestSuite($classname=false) {
    // Find all methods of the given class whose name starts with
    // "test" and add them to the test suite.

    // PHP3: We are just _barely_ able to do this with PHP's limited
    // introspection...  Note that PHP seems to store method names in
    // lower case, and we have to avoid the constructor function for
    // the TestCase class superclass.  Names of subclasses of TestCase
    // must not start with "Test" since such a class will have a
    // constructor method name also starting with "test" and we can't
    // distinquish such a construtor from the real test method names.
    // So don't name any TestCase subclasses as "Test..."!

    // PHP4:  Never mind all that.  We can now ignore constructor
    // methods, so a test class may be named "Test...".

    if (empty($classname))
      return;
    $this->fClassname = $classname;

    if (floor(phpversion()) >= 4) {
      // PHP4 introspection, submitted by Dylan Kuhn

      $names = get_class_methods($classname);
      while (list($key, $method) = each($names)) {
        if (preg_match('/^test/', $method)) {
          $test = new $classname($method);
          if (strcasecmp($method, $classname) == 0 || is_subclass_of($test, $method)) {
            // Ignore the given method name since it is a constructor:
            // it's the name of our test class or it is the name of a
            // superclass of our test class.  (This code smells funny.
            // Anyone got a better way?)

            //print "skipping $method<br>";
          }
          else {
            $this->addTest($test);
          }
        }
      }
    }
    else {  // PHP3
      $dummy = new $classname("dummy");
      $names = (array) $dummy;
      while (list($key, $value) = each($names)) {
        $type = gettype($value);
        if ($type == "user function" && preg_match('/^test/', $key)
        && $key != "testcase") {  
          $this->addTest(new $classname($key));
        }
      }
    }
  }

  function addTest($test) {
    /* Add TestCase or TestSuite to this TestSuite */
    $this->fTests[] = $test;
  }

  function run(&$testResult) {
    /* Run all TestCases and TestSuites comprising this TestSuite,
       accumulating results in the given TestResult object. */
    $testResult->setSuite($this);
    reset($this->fTests);
    while (list($na, $test) = each($this->fTests)) {
      if ($testResult->shouldStop())
		break;
      $test->run($testResult);
    }
  }

  function countTestCases() {
    /* Number of TestCases comprising this TestSuite (including those
       in any constituent TestSuites) */
    $count = 0;
    reset($this->fTests);
    while (list($na, $test_case) = each($this->fTests)) {
      $count += $test_case->countTestCases();
    }
    return $count;
  }
}


class TestFailure {
  /* Record failure of a single TestCase, associating it with the
     PHPUNITException that occurred */
  var $fFailedTestName;
  var $fPHPUNITException;

  function TestFailure(&$test, &$PHPUNITException) {
    $this->fFailedTestName = $test->name();
    $this->fPHPUNITException = $PHPUNITException;
  }

  function getPHPUNITExceptions() {
      // deprecated
      return array($this->fPHPUNITException);
  }
  function getPHPUNITException() {
      return $this->fPHPUNITException;
  }

  function getTestName() {
    return $this->fFailedTestName;
  }
}


class TestResult {
  /* Collect the results of running a set of TestCases. */
  var $fFailures = array();
  var $fErrors = array();
  var $fRunTests = 0;
  var $fStop = false;
  var $suite = null; // the top-level suite that is being run.

  function TestResult() { }

  function setSuite(&$testSuite) {
  	
  	$this->suite = $testSuite;
  		
  }	

  function countAllTestsInSuite() {
  	
  	return $this->suite->countTestCases();
  		
  }

  function _endTest($test) /* protected */ {
      /* specialize this for end-of-test action, such as progress
	 reports  */
  }

  function addError($test, $PHPUNITException) {
      $this->fErrors[] = new TestFailure($test, $PHPUNITException);
  }

  function addFailure($test, $PHPUNITException) {
      $this->fFailures[] = new TestFailure($test, $PHPUNITException);
  }

  function getFailures() {
    return $this->fFailures;
  }

  function run(&$test) {
    /* Run a single TestCase in the context of this TestResult */
    $this->_startTest($test);
    $this->fRunTests++;

    $test->runBare();

    /* this is where JUnit would catch AssertionFailedError */
    $PHPUNITExceptions = $test->getPHPUNITExceptions();
    while (list($key, $PHPUNITException) = each($PHPUNITExceptions)) {
	if ($PHPUNITException->type == 'ERROR')
	    $this->addError($test, $PHPUNITException);
	else if ($PHPUNITException->type == 'FAILURE')
	    $this->addFailure($test, $PHPUNITException);
    }
    //    if ($PHPUNITExceptions)
    //      $this->fFailures[] = new TestFailure($test, $PHPUNITExceptions);
    $this->_endTest($test);
  }

  function countTests() {
    return $this->fRunTests;
  }

  function shouldStop() {
    return $this->fStop;
  }

  function _startTest($test) /* protected */ {
      /* specialize this for start-of-test actions */
  }

  function stop() {
    /* set indication that the test sequence should halt */
    $this->fStop = true;
  }

  function errorCount() {
      return count($this->fErrors);
  }
  function failureCount() {
      return count($this->fFailures);
  }
}


class TextTestResult extends TestResult {
  /* Specialize TestResult to produce text/html report */
  function TextTestResult() {
    $this->TestResult();  // call superclass constructor
  }
  
  function report() {
    /* report result of test run */
    $nRun = $this->countTests();
    $nFailures = $this->failureCount();
    $nErrors = $this->errorCount();
    printf("<p>%s test%s run.<br>\n", $nRun, ($nRun == 1) ? '' : 's');
    printf("%s failure%s.<br>\n", $nFailures, ($nFailures == 1) ? '' : 's');
    printf("%s error%s.<br>\n", $nErrors, ($nErrors == 1) ? '' : 's');

    if ($nFailures > 0) {
	print("<h2>Failures</h2>");
	print("<ol>\n");
	$failures = $this->getFailures();
	while (list($i, $failure) = each($failures)) {
	    $failedTestName = $failure->getTestName();
	    printf("<li>%s\n", $failedTestName);

	    $PHPUNITExceptions = $failure->getPHPUNITExceptions();
	    print("<ul>");
	    while (list($na, $PHPUNITException) = each($PHPUNITExceptions))
		printf("<li>%s\n", $PHPUNITException->getMessage());
	    print("</ul>");
	}
	print("</ol>\n");
    }

    if ($nErrors > 0) {
	print("<h2>Errors</h2>");
	print("<ol>\n");
	reset($this->fErrors);
	while (list($i, $error) = each($this->fErrors)) {
	    $erroredTestName = $error->getTestName();
	    printf("<li>%s\n", $failedTestName);

	    $PHPUNITException = $error->getPHPUNITException();
	    print("<ul>");
	    printf("<li>%s\n", $PHPUNITException->getMessage());
	    print("</ul>");
	}
	print("</ol>\n");

    }
  }

  function _startTest($test) {
      if (phpversion() > '4') {
	  printf("%s - %s ", get_class($test), $test->name());
      } else {
	  printf("%s ", $test->name());
      }
    flush();
  }

  function _endTest($test) {
    $outcome = $test->failed()
       ? "<font color=\"red\">FAIL</font>"
       : "<font color=\"green\">ok</font>";
    printf("$outcome<br>\n");
    flush();
  }
}


/**
* This was created because the standard test result provided looks like
* rubbish.
*
* Changes:
* <ol><li><b>({@link http://sourceforge.net/tracker/index.php?func=detail&aid=648413&group_id=10610&atid=110610 Bug #648413}
* 2003/03/09 bmatzelle)</b> CSS reference missing from pretty test.
*
* @author BJG
* @since 2001/11/17
*/
class PrettyTestResult extends TestResult {
	// {{{ construct()
	/**
	 * Specialize TestResult to produce text/html report.
	 */
	function PrettyTestResult() {
		$this->TestResult();  // call superclass constructor
		// NOTE: one wonders why the cellspacing,cellpadding,border,width,align when there is a css class??
		echo '<h2>Tests</h2>',"\n",
		     '<table cellspacing="1" cellpadding="1" border="0" width="90%" align="center" class="details">',"\n\t",
			 '<tr><th>Class</th><th>Function</th><th>Success?</th></tr>'."\n";
	}
	// }}}
  
  function report() {
	echo "</TABLE>";
    /* report result of test run */
    $nRun = $this->countTests();
    $nFailures = $this->failureCount();
    $nErrors = $this->errorCount();
	echo "<h2>Summary</h2>";

    printf("<p>%s test%s run.<br>\n", $nRun, ($nRun == 1) ? '' : 's');
    printf("%s failure%s.<br>\n", $nFailures, ($nFailures == 1) ? '' : 's');
    printf("%s error%s.<br>\n", $nErrors, ($nErrors == 1) ? '' : 's');
    if ($nFailures == 0)
      return;

	echo "<h2>Failure Details</h2>";
    print("<ol>\n");
    $failures = $this->getFailures();
    while (list($i, $failure) = each($failures)) {
      $failedTestName = $failure->getTestName();
      printf("<li>%s\n", $failedTestName);

      $PHPUNITExceptions = $failure->getPHPUNITExceptions();
      print("<ul>");
      while (list($na, $PHPUNITException) = each($PHPUNITExceptions))
	printf("<li>%s\n", $PHPUNITException->getMessage());
      print("</ul>");
    }
    print("</ol>\n");
  }
	// {{{ _startTest($test)
	function _startTest($test) {
		printf("\t".'<tr><td>%s </td><td>%s </td>', $test->classname(), $test->name());
		flush();
	}
	// }}}
	// {{{ _endTest($test)
	function _endTest($test) {
		$outcome = $test->failed()
		         ? ' class="Failure">FAIL'
				 : ' class="Pass">OK';
		printf("<td$outcome</td></tr>\n");
		flush();
	}
	// }}}
}

class TestRunner {
  /* Run a suite of tests and report results. */
  function run(&$suite) {
      $result = new PrettyTestResult();
      $suite->run($result);
      $result->report();
  }
}

?>
Return current item: XMLNuke Web Development Framework XML