// // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the // Free Software Foundation, either version 3 of the License, or (at your // option) any later version. // // This program is distributed in the hope that it will be useful, but // *WITHOUT ANY WARRANTY*; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General // Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program. If not, see . // Topic: Description // // Useful for invoking series of small tests, probably from a Makefile. The // testing section of this library's Makefile follows. Note that we're using // "find" rather than iterate with PHP's opendir() to make sure that a fatal // error in one test file does not affect any other files. This prevents us // from knowing the length of the longest file for display alignment, but I // prefer function over form in this case. // // (begin example) // test: dep // @find t -name '*.php' -exec php -d include_path=lib -f '{}' ';' // @echo "*** See 'test.log' for details." // (end example) // // The above iterates through each ".php" file in directory "t/" and any // subdirectory therein, displays a summary of results on screen and saves // full debugging output in "test.log". // // Example test file: // // (begin example) // require_once 'Test.inc'; // // ok(function_exists('a_function_of_yours'), true); # This is test 1 // // okDiff('foobar', a_function_of_yours('raboof')); # This is test 2 // (end example) // Private Class: Test // class Test { // Private Constructor: __construct // function __construct() { $this->goods = 0; $this->total = 0; $this->faileds = Array(); $this->log = fopen("test.log","a"); ob_implicit_flush(false); ob_start(); } // Private Destructor: __destruct // function __destruct() { ob_end_clean(); if ($this->goods >= $this->total) echo " ok"; else echo " FAILED\n\tFailed test numbers: " . join(',', $this->faileds); echo "\n"; if ($this->log) fclose($this->log); // I like things nice and explicit. } // Private Method: _ok // // See . function ok($bool, $fatal = false) { $this->total++; $out = ob_get_contents(); ob_end_clean(); // PHP has a bug, cannot use ob_get_clean() in CLI mode; closes the OB! if ($bool) { $this->goods++; if ($this->log) fwrite($this->log, "*** {$_SERVER['PHP_SELF']} TEST {$this->total} OK\n"); } else { $this->faileds[] = $this->total; if ($this->log) fwrite($this->log, "*** {$_SERVER['PHP_SELF']} TEST {$this->total} FAILED. OUTPUT:\n\n{$out}\n\n"); }; echo sprintf("\r%-50s %3s / %3s", $_SERVER['PHP_SELF'], $this->goods, $this->total); ob_start(); // Restart OB to complete PHP bug workaround. Makes progress output easier anyway. // Bail out of everything if we failed a fatal-type test. if (!$bool && $fatal) { // PHP 5 is nice and will still call __destruct(). Better in fact // than if I tried to do so explicitly here. exit(0); }; } } // Necessary to simulate atexit() with class destructor. $globalTestInstance = new Test(); // Convenient syntax inspired by Perl's Test.pm. // Function: ok // // Log a test result. If a second argument is true, this will be the last // test performed in this file if it fails. function ok($bool, $fatal = false) { global $globalTestInstance; $globalTestInstance->ok($bool, $fatal); }; // Function: okDiff // // Wrapper around and . Will display any difference // between arguments 1 and 2 and consider the test a success if they match // *perfectly*. A match means that both not only represent the same value, // but are also of the same type. (i.e. "2", 2 and 2.0 are three different // things.) If the arguments are arrays, they are compared properly whether // they are hashes or indexed, in both directions with full recursion to find // any possible differences, thanks to . // // As with , a if a third argument is true, this will be the last test // performed in this file if it fails. function okDiff($left, $right, $fatal = false) { require_once('array_compare.inc'); var_dump($diff = array_compare($left, $right)); ok($diff === false); }; ?>