PHP Unit Testing Framework 1
A Unit testing framework for PHP.

php_unit_test.php

Go to the documentation of this file.
00001 <?php
00034 
00157 
00166 class EventType
00167 {  
00168   private $value; // Stores the event type
00169   
00174   private function __construct($value)
00175   {
00176     $this->value = $value;
00177   }
00178   
00182   public static function PASS()
00183   {
00184     return new EventType(1);
00185   }
00186 
00190   public static function PASS_MSG()
00191   {
00192     return new EventType(2);
00193   }
00194 
00198   public static function FAIL()
00199   {
00200     return new EventType(3);
00201   }
00202 
00206   public static function FAIL_MSG()
00207   {
00208     return new EventType(4);
00209   }
00210   
00215   public static function ERROR()
00216   {
00217     return new EventType(5);
00218   }
00223   public static function USER_MSG()
00224   { 
00225     return new EventType(6); 
00226   }
00227 
00232   public static function SYS_MSG() 
00233   { 
00234     return new EventType(7); 
00235   }
00236 
00242   public static function EXCEPTION_THROWN() 
00243   {
00244     return new EventType(8);
00245   }
00246 
00250   public static function START_SETUP() 
00251   { 
00252     return new EventType(9);
00253   }
00254 
00259   public static function END_SETUP()    
00260   { 
00261     return new EventType(10);
00262   }
00263 
00267   public static function START_RUN() 
00268   { 
00269     return new EventType(11); 
00270   }
00271 
00275   public static function END_RUN()      
00276   {
00277     return new EventType(12); 
00278   }
00279 
00283   public static function START_TEAR_DOWN()  
00284   {
00285     return new EventType(13); 
00286   }
00287 
00291   public static function END_TEAR_DOWN() 
00292   {
00293     return new EventType(14); 
00294   }
00295 }
00296 
00308 class Event
00309 {
00310   private $type;       // The event type.
00311   private $time;       // The time of the event.
00312   private $reason;     // The reason for the event.
00313   private $message;    // A user defined message for the event (commentary).
00314   private $actual;     // The actual value
00315   private $comparison; // What was used in the comparison
00316   private $file;       // The filename where the event occurred.
00317   private $line;       // And the line number
00318 
00326   private static function CreateValue($value)
00327   {
00328     $type = gettype($value);
00329     switch ($type)
00330     {
00331       case 'NULL':
00332         $str = 'NULL';
00333         break;
00334       case 'string':
00335       case 'integer':
00336       case 'double':
00337         $str = (string)$value;
00338         break;
00339       case 'boolean':
00340         $str = ($value ? 'True' : 'False');
00341         break;
00342       default:
00343         $str = var_export($value, true);
00344         break;
00345     }
00346     return array('type' => $type, 'value' => $str);
00347   }
00348 
00360   public function __construct(EventType $type,
00361                               $reason,
00362                               $message,
00363                               $actual,
00364                               $comparison,
00365                               $file,
00366                               $line)
00367   {
00368     list($usec, $sec) = explode(' ', microtime());
00369     $usec = substr($usec . '00000', 2, 3);
00370     $now = new DateTime('@' . $sec);
00371     $this->time = $now->format('d M y, H:i:s.' . $usec .  ' O');
00372     $this->type = $type;
00373     $this->reason = $reason;
00374     $this->message = $message;
00375     $this->actual = Event::CreateValue($actual);
00376     $this->comparison = Event::CreateValue($comparison);
00377     $this->file = $file;
00378     $this->line = $line;
00379   }
00380   
00385   public function GetType()
00386   {
00387     return $this->type;
00388   }
00389   
00394   public function GetTypeAsString()
00395   {
00396     switch ($this->type)
00397     {
00398       case EventType::PASS():
00399         return 'PASS';
00400       case EventType::PASS_MSG():
00401         return 'PASS_MSG';
00402       case EventType::FAIL():
00403         return 'FAIL';
00404       case EventType::FAIL_MSG():
00405         return 'FAIL_MSG';
00406       case EventType::ERROR():
00407         return 'ERROR';
00408       case EventType::USER_MSG():
00409         return 'USER_MSG';
00410       case EventType::SYS_MSG():
00411         return 'SYS_MSG';
00412       case EventType::EXCEPTION_THROWN():
00413         return 'EXCEPTION_THROWN';
00414       case EventType::START_SETUP():
00415         return 'START_SETUP';
00416       case EventType::END_SETUP():
00417         return 'END_SETUP';
00418       case EventType::START_RUN():
00419         return 'START_RUN';
00420       case EventType::END_RUN():
00421         return 'END_RUN';
00422       case EventType::START_TEAR_DOWN():
00423         return 'START_TEAR_DOWN';
00424       case EventType::END_TEAR_DOWN():
00425         return 'END_TEAR_DOWN';
00426     }
00427     return 'This chould never occur!';
00428   }
00429   
00436   public function GetTime()
00437   {
00438     return $this->time;
00439   }
00440   
00445   public function GetReason()
00446   {
00447     return $this->reason;
00448   }
00449   
00455   public function GetMessage()
00456   {
00457     return $this->message;
00458   }
00459   
00465   public function GetActualType()
00466   {
00467     return $this->actual['type'];
00468   }
00469   
00475   public function GetActualValue()
00476   {
00477     return $this->actual['value'];
00478   }
00479   
00485   public function GetComparisonType()
00486   {
00487     return $this->comparison['type'];
00488   }
00489   
00495   public function GetComparisonValue()
00496   {
00497     return $this->comparison['value'];
00498   }
00499 
00504   public function GetFile()
00505   {
00506     return $this->file;
00507   }
00508   
00513   public function GetLine()
00514   {
00515     return $this->line;
00516   }
00517 }
00518 
00526 class TestCaseResult
00527 {
00534   protected function __construct($name, $id)
00535   {
00536     $this->success = true;
00537     $this->testEvents = array();
00538     $this->name = $name;
00539     $this->testCaseId = $id;
00540     $this->description = 'No description.';
00541   }
00542   
00547   public function GetName()
00548   {
00549     return $this->name;
00550   }
00551 
00556   public function GetID()
00557   {
00558     return $this->testCaseId;
00559   }
00560   
00565   public function GetDescription()
00566   {
00567     return $this->description;
00568   }
00569   
00574   public function GetNumberOfEvents()
00575   {
00576     return count($this->testEvents);
00577   }
00578   
00585   public function GetEvent($index)
00586   {
00587     return $this->testEvents[$index];
00588   }
00589   
00595   public function TestPassed()
00596   {
00597     return $this->success;
00598   }
00599 }
00600 
00609 class TestCaseResultConstructor extends TestCaseResult
00610 {
00611   protected $success;       
00612   protected $testCaseId;    
00613   protected $name;          
00614   protected $description;   
00615   protected $testEvents;    
00616   
00622   public function __construct($name, $id)
00623   {
00624     parent::__construct($name, $id);
00625   }
00626   
00635   public function AddDetail(EventType $type,
00636                             $reason,
00637                             $message = '',
00638                             $actual = '',
00639                             $comparison = '')
00640   {
00641     if (EventType::FAIL() == $type ||
00642         EventType::FAIL_MSG() == $type ||
00643         EventType::ERROR() == $type)
00644     {
00645       $this->success = false;
00646     }
00647     $trace = debug_backtrace();
00648     $line = '';
00649     $file = '';
00650     foreach ($trace as $item)
00651     {
00652       if ('Assert' == $item['class'])
00653       {
00654         $line = $item['line'];
00655         $file = $item['file'];
00656         break;        
00657       }
00658     }
00659     $this->testEvents[] = new Event($type,
00660                                     $reason,
00661                                     $message,
00662                                     $actual,
00663                                     $comparison,
00664                                     $file,
00665                                     $line);
00666   }
00667   
00674   public function AddException($place, Exception &$exception)
00675   {
00676     $this->success = false;
00677     $this->testEvents[] = new Event(EventType::EXCEPTION_THROWN(),
00678                                     $place,
00679                                     $exception->getMessage(),
00680                                     null,
00681                                     null,
00682                                     $exception->getFile(),
00683                                     $exception->getLine());
00684   
00685   }
00686   
00692   public function AddTimeStamp(EventType $type)
00693   {
00694     $this->AddDetail($type, 'Marker');
00695   }
00696   
00702   public function AddMessage($message, $type)
00703   {
00704     if (EventType::SYS_MSG() == $type)
00705     {
00706       $this->AddDetail($type, $message);
00707     }
00708     else
00709     {
00710       $this->AddDetail($type, '', $message);
00711     }
00712   }
00713   
00720   public function SetDetails($name, $id, $description)
00721   {
00722     $this->name = $name;
00723     $this->description = $description;
00724     $this->testCaseId = $id;
00725   }
00726 }
00727 
00734 class TestCaseBase
00735 {
00736   protected $testCaseResults; 
00737   private $name;              // The name for the test case.
00738   private $id;                // The test case ID.
00739   private $description;       // A description for the test case.
00740   private static $testCaseCounter = 1; // For when test case ID is not given.
00741 
00747   public function Init(TestCaseResultConstructor &$testCaseResults)
00748   {
00749     $this->testCaseResults = $testCaseResults;
00750   }
00751   
00758   protected function __construct($name, $description, $id)
00759   {
00760     $this->name = (null == $name ? get_class($this) : $name);
00761     $this->description = (null == $description ? 'No description.' : $description);
00762     if (null == $id)
00763     {
00764       $id = 'TEST' . TestCaseBase::$testCaseCounter++;
00765     }
00766     $this->id = $id;
00767   }
00768 
00773   public function GetName()
00774   {
00775     return $this->name;
00776   }
00777 
00782   public function GetID()
00783   {
00784     return $this->id;
00785   }
00786   
00791   public function GetDescription()
00792   {
00793     return $this->description;
00794   }
00795 }
00796 
00803 interface Equality
00804 {
00810   public function Equals($obj);
00811 }
00812 
00817 class CompareValuesResult
00818 {
00819   private $value;
00820   
00825   private function __construct($value)
00826   {
00827     $this->value = $value;
00828   }
00829 
00833   public static function EQUAL()
00834   {
00835     return new CompareValuesResult(1);
00836   }
00837 
00841   public static function NOT_EQUAL()
00842   {
00843     return new CompareValuesResult(2);
00844   }
00845 
00852   public static function INCOMPARABLE()
00853   {
00854     return new CompareValuesResult(3);
00855   }
00856 }
00857 
00865 class Assert extends TestCaseBase
00866 {
00867   private static $buffers = 0;
00868   
00877   public static function DieOnError($errNo, $errStr, $file, $line)
00878   {
00879     die("Error: [$errNo] $errStr in $file at $line");
00880   }
00881   
00889   protected function __construct($name, $description, $id)
00890   {
00891     parent::__construct($name, $description, $id);
00892     set_error_handler('Assert::DieOnError'); // So warnings etc are not lost!
00893     ob_start();
00894   }
00895   
00899   public function __destruct()
00900   {
00901     ob_end_flush();
00902   }
00903 
00908   public function AddMessage($message)
00909   {
00910     $this->testCaseResults->AddMessage($message, EventType::USER_MSG());
00911   }
00912 
00917   public function Fail($message)
00918   {
00919     $this->testCaseResults->AddMessage($message, EventType::FAIL_MSG());
00920   }
00921 
00926   public function Pass($message)
00927   {
00928     $this->testCaseResults->AddMessage($message, EventType::PASS_MSG());
00929   }
00930   
00934   //                          compare it.
00936   private static function CanCompare($value)
00937   {
00938     $type = gettype($value);
00939     return ('string' == $type || 'integer' == $type || 'double' == $type ||
00940             'NULL' == $type   || 'boolean' == $type); 
00941   }
00942  
00943   
00949   private static function CompareValues($actual, $toBeComparedWith)
00950   {
00951     $actualType = gettype($actual);
00952     $toBeComparedWithType = gettype($toBeComparedWith);
00953     if ($actualType != $toBeComparedWithType)
00954     {
00955       return CompareValuesResult::INCOMPARABLE();
00956     }
00957     
00958     // Type are the same type
00959     
00960     switch ($toBeComparedWithType)
00961     {
00962       case 'NULL':
00963       case 'boolean':
00964       case 'integer':
00965       case 'double':
00966       case 'string':
00967         return ($actual == $toBeComparedWith ? CompareValuesResult::EQUAL()
00968                                              : CompareValuesResult::NOT_EQUAL());
00969       case 'resource':
00970         return CompareValuesResult::INCOMPARABLE();
00971       case 'array':
00972         foreach ($toBeComparedWith as $k => $v)
00973         {
00974           if (array_key_exists($k, $actual))
00975           {
00976             $result = Assert::CompareValues($actual[$k], $v);
00977             if ($result != CompareValuesResult::EQUAL()) return $result;
00978           }
00979           else
00980           {
00981             return CompareValuesResult::INCOMPARABLE();
00982           }
00983         
00984         }
00985         return CompareValuesResult::EQUAL();
00986       case 'object':
00987         if ($toBeComparedWith instanceof Equality)
00988         {
00989           return ($toBeComparedWith->Equals($actual) ? CompareValuesResult::EQUAL()
00990                                                      : CompareValuesResult::NOT_EQUAL());
00991         }
00992         else
00993         {
00994           return CompareValuesResult::INCOMPARABLE();
00995         }
00996       default:
00997         return CompareValuesResult::INCOMPARABLE();
00998     }
00999   }
01000   
01047   public function AssertEquals($actual, $expected, $message = '')
01048   {
01049     switch (Assert::CompareValues($actual, $expected))
01050     {
01051       case CompareValuesResult::EQUAL():
01052         $this->testCaseResults->AddDetail(EventType::PASS(),
01053                                           'AssertEquals: The values are equal.',
01054                                           $message,
01055                                           $actual,
01056                                           $expected);
01057         break;
01058       case CompareValuesResult::NOT_EQUAL():
01059         $this->testCaseResults->AddDetail(EventType::FAIL(),
01060                                           'AssertEquals: The values are not equal.',
01061                                           $message,
01062                                           $actual,
01063                                           $expected);
01064         break;
01065       default:
01066         if (Assert::CanCompare($actual) && Assert::CanCompare($expected))
01067         {
01068           if ($actual == $expected)
01069           {
01070             $this->testCaseResults->AddDetail(EventType::ERROR(),
01071                                               'AssertEquals: Values cannot be compared. After type conversion they are equal.',
01072                                               $message,
01073                                               $actual,
01074                                               $expected);
01075           }
01076           else
01077           {
01078             $this->testCaseResults->AddDetail(EventType::ERROR(),
01079                                               'AssertEquals: Values cannot be compared. After type conversion they are not equal.',
01080                                               $message,
01081                                               $actual,
01082                                               $expected);
01083           }
01084       }
01085       else
01086       {
01087         $this->testCaseResults->AddDetail(EventType::ERROR(),
01088                                           'AssertEquals: Values cannot be compared.',
01089                                           $message,
01090                                           $actual,
01091                                           $expected);
01092       }
01093       break;
01094     }
01095   }
01096   
01107   public function AssertNotEquals($actual, $expected, $message = '')
01108   {
01109     switch (Assert::CompareValues($actual, $expected))
01110     {
01111       case CompareValuesResult::EQUAL():
01112         $this->testCaseResults->AddDetail(EventType::FAIL(),
01113                                           'AssertNotEquals: The values are equal.',
01114                                           $message,
01115                                           $actual,
01116                                           $expected);
01117         break;
01118       case CompareValuesResult::NOT_EQUAL():
01119         $this->testCaseResults->AddDetail(EventType::PASS(),
01120                                           'AssertNotEquals: The values are not equal.',
01121                                           $message,
01122                                           $actual,
01123                                           $expected);
01124         break;
01125       default:
01126         if (Assert::CanCompare($actual) && Assert::CanCompare($expected))
01127         {
01128           if ($actual == $expected)
01129           {
01130             $this->testCaseResults->AddDetail(EventType::ERROR(),
01131                                               'AssertNotEquals: Values cannot be compared. After type conversion they are equal.',
01132                                               $message,
01133                                               $actual,
01134                                               $expected);
01135           }
01136           else
01137           {
01138             $this->testCaseResults->AddDetail(EventType::ERROR(),
01139                                               'AssertNotEquals: Values cannot be compared. After type conversion they are not equal.',
01140                                               $message,
01141                                               $actual,
01142                                               $expected);
01143           }
01144       }
01145       else
01146       {
01147         $this->testCaseResults->AddDetail(EventType::ERROR(),
01148                                           'AssertNotEquals: Values cannot be compared.',
01149                                           $message,
01150                                           $actual,
01151                                           $expected);
01152       }
01153       break;
01154     }  
01155   }
01156   
01164   public function AssertMatches($actual, $pattern, $message = '')
01165   {
01166     if ('string' != gettype($actual) ||
01167         'string' != gettype($pattern))
01168     {
01169       $this->testCaseResults->AddDetail(EventType::ERROR(),
01170                                         'AssertMatches: Both parameters need to be strings.',
01171                                         $message,
01172                                         $actual,
01173                                         $pattern);
01174       return;
01175     }
01176     $match = preg_match($pattern, $actual);
01177     $this->testCaseResults->AddDetail($match > 0 ? EventType::PASS() : EventType::FAIL(),
01178                                       'AssertMatches: ' . $match . ' matches found.',
01179                                       $message,
01180                                       $actual,
01181                                       $pattern);
01182   }
01183   
01191   public function AssertNotMatches($actual, $pattern, $message = '')
01192   {
01193     if ('string' != gettype($actual) ||
01194         'string' != gettype($pattern))
01195     {
01196       $this->testCaseResults->AddDetail(EventType::ERROR(),
01197                                         'AssertNotMatches: Both parameters need to be strings.',
01198                                         $message,
01199                                         $actual,
01200                                         $pattern);
01201       return;
01202     }
01203     $match = preg_match($pattern, $actual);
01204     $this->testCaseResults->AddDetail($match > 0 ? EventType::FAIL() : EventType::PASS(),
01205                                       'AssertNotMatches: ' . $match . ' matches found.',
01206                                       $message,
01207                                       $actual,
01208                                       $pattern);
01209   }
01210   
01215   public function ReStartOutputChecking()
01216   {
01217     ob_flush();
01218   }
01219   
01227   public function AssertOutputEquals($expected, $message = '')
01228   {
01229     $actual = ob_get_contents();
01230     if ('string' != gettype($expected))
01231     {
01232       $this->testCaseResults->AddDetail(EventType::ERROR(),
01233                                         'AssertOutputEquals: Expected need to be a string.',
01234                                         $message,
01235                                         $actual,
01236                                         $expected);
01237       return;
01238     }
01239     if ($actual == $expected)
01240     {
01241     
01242       $this->testCaseResults->AddDetail(EventType::PASS(),
01243                                         'AssertOutputEquals: Output matches.',
01244                                         $message,
01245                                         $actual,
01246                                         $expected);
01247     }
01248     else
01249     {
01250       $this->testCaseResults->AddDetail(EventType::FAIL(),
01251                                         'AssertOutputEquals: Output does not match.',
01252                                         $message,
01253                                         $actual,
01254                                         $expected);
01255     }
01256   
01257   }
01258   
01266   public function AssertOutputDiffers($expected, $message = '')
01267   {
01268     $actual = ob_get_contents();
01269     if ('string' != gettype($expected))
01270     {
01271       $this->testCaseResults->AddDetail(EventType::ERROR(),
01272                                         'AssertOutputDiffers: Expected need to be a string.',
01273                                         $message,
01274                                         $actual,
01275                                         $expected);
01276       return;
01277     }
01278     if ($actual == $expected)
01279     {
01280     
01281       $this->testCaseResults->AddDetail(EventType::FAIL(),
01282                                         'AssertOutputDiffers: Output matches.',
01283                                         $message,
01284                                         $actual,
01285                                         $expected);
01286     }
01287     else
01288     {
01289       $this->testCaseResults->AddDetail(EventType::PASS(),
01290                                         'AssertOutputDiffers: Output does not match.',
01291                                         $message,
01292                                         $actual,
01293                                         $expected);
01294     }
01295   }
01296 
01304   public function AssertOutputMatches($pattern, $message = '')
01305   {
01306     $actual = ob_get_contents();
01307     $actual = ob_get_contents();
01308     if ('string' != gettype($pattern))
01309     {
01310       $this->testCaseResults->AddDetail(EventType::ERROR(),
01311                                         'AssertOutputMatches: Expected need to be a string.',
01312                                         $message,
01313                                         $actual,
01314                                         $pattern);
01315       return;
01316     }
01317     
01318     $match = preg_match($pattern, $actual);
01319     $this->testCaseResults->AddDetail($match > 0 ? EventType::PASS() : EventType::FAIL(),
01320                                       'AssertOutputMatches: ' . $match . ' matches found.',
01321                                       $message,
01322                                       $actual,
01323                                       $pattern);
01324   }
01325   
01333   public function AssertOutputNotMatches($pattern, $message = '')
01334   {
01335     $actual = ob_get_contents();
01336     $actual = ob_get_contents();
01337     if ('string' != gettype($pattern))
01338     {
01339       $this->testCaseResults->AddDetail(EventType::ERROR(),
01340                                         'AssertOutputNotMatches: Expected need to be a string.',
01341                                         $message,
01342                                         $actual,
01343                                         $pattern);
01344       return;
01345     }
01346 
01347     $match = preg_match($pattern, $actual);
01348     $this->testCaseResults->AddDetail($match > 0 ? EventType::FAIL() : EventType::PASS(),
01349                                       'AssertOutputNotMatches: ' . $match . ' matches found.',
01350                                       $message,
01351                                       $actual,
01352                                       $pattern);
01353   }
01354 }
01355 
01365 abstract class TestCase extends Assert
01366 {
01373   public function __construct($name = null, $description = null, $id = null)
01374   {
01375     parent::__construct($name, $description, $id);
01376   }
01377 
01382   public abstract function SetUp();
01383   
01389   public abstract function Run();
01390 
01396   public abstract function TearDown();
01397 }
01398 
01409 class TestSuite
01410 {
01411   private $testCases;    // A list of test cases.
01412   private $allPassed;    // True if all passed, false otherwise.
01413   
01417   public function __construct()
01418   {
01419     $this->anyFailed = false;
01420     $this->testCases = array();
01421   }
01422  
01426   public function AllPassed()
01427   {
01428     return $this->allPassed;
01429   }
01430   
01435   public function AddTest($className)
01436   {
01437     $this->testCases[] = $className;
01438   }
01439   
01446   public function Run(TestSuiteResult &$results)
01447   {
01448     $this->allPassed = true;
01449     
01450     foreach ($this->testCases as $className)
01451     {
01452       // Loop through test cases
01453       
01454       $testCase = new $className();
01455       $testCaseResult = new TestCaseResultConstructor($className, $testCase->GetID());
01456       if (!$testCase instanceof TestCase)
01457       {
01458         throw new Exception('The class "' . $className . '" is not an instance of TestCase!');
01459       }
01460       
01461       // Initialise the test case
01462       $testCase->Init($testCaseResult);
01463       
01464       // Perform set up
01465       $testCaseResult->AddTimeStamp(EventType::START_SETUP());
01466       try
01467       {
01468         $testCase->SetUp();
01469         $okToRun = $testCaseResult->TestPassed();
01470       }
01471       catch (Exception $e)
01472       {
01473         $testCaseResult->SetDetails($testCase->GetName(),
01474                                     $testCase->GetID(),
01475                                     $testCase->GetDescription());
01476         $testCaseResult->AddException('Uncaught exception thrown in \'SetUp\'.',
01477                                       $e);
01478         $testCaseResult->AddTimeStamp(EventType::END_SETUP());
01479         $okToRun = false;
01480       }
01481 
01482       $testCaseResult->SetDetails($testCase->GetName(),
01483                                   $testCase->GetID(),
01484                                   $testCase->GetDescription());
01485 
01486       if ($okToRun)
01487       {
01488         // As SetUp ran successfully, run the test
01489         $testCaseResult->AddMessage('Setup completed.', EventType::SYS_MSG());
01490         $testCaseResult->AddTimeStamp(EventType::END_SETUP());
01491         try
01492         {
01493           $testCaseResult->AddTimeStamp(EventType::START_RUN());
01494           $testCase->Run();
01495           $testCaseResult->AddMessage('Test case completed.', EventType::SYS_MSG());
01496           $testCaseResult->AddTimeStamp(EventType::END_RUN());
01497         }
01498         catch (Exception $e)
01499         {
01500           $testCaseResult->AddException('Uncaught exception thrown in \'Run\'.',
01501                                         $e);
01502           $testCaseResult->AddTimeStamp(EventType::END_RUN());
01503           // Try to tear down so potentially other tests can run!
01504         }
01505       }
01506       else
01507       {
01508         $testCaseResult->AddMessage('Setup failed - Not running test case.', EventType::SYS_MSG());
01509       }
01510 
01511       // Tidy up
01512       try
01513       {
01514         $testCaseResult->AddTimeStamp(EventType::START_TEAR_DOWN());
01515         $testCase->TearDown();
01516         $testCaseResult->AddMessage('TearDown completed.', EventType::SYS_MSG());
01517         $testCaseResult->AddTimeStamp(EventType::END_TEAR_DOWN());
01518       }
01519       catch (Exception $e)
01520       {
01521         $testCaseResult->AddException('Uncaught exception thrown in \'TearDown\'.',
01522                                       $e);
01523         $testCaseResult->AddTimeStamp(EventType::END_TEAR_DOWN());
01524       }
01525       $results->AddTestCaseResult($testCaseResult);
01526       $this->allPassed = $this->allPassed && $testCaseResult->TestPassed();
01527       $testCase = null; // Should call the garbage collector
01528     }
01529   }
01530 }
01531 
01539 class TestSuiteResult
01540 {
01541   protected $testCaseResults;  
01542   
01546   public function __construct()
01547   {
01548     $testCaseResults = array();
01549   }
01550   
01556   public function AddTestCaseResult(TestCaseResultConstructor &$result)
01557   {
01558     $this->testCaseResults[] = $result;
01559   }
01560 }
01561 
01574 abstract class TestRunner extends TestSuiteResult
01575 {
01580   public function GetNumberOfTestCaseResults()
01581   {
01582     return count($this->testCaseResults);
01583   }
01584   
01590   public function GetTestCaseResult($index)
01591   {
01592     return $this->testCaseResults[$index];
01593   }
01594   
01611   protected function Run(TestSuite &$suite,
01612                          $filename,
01613                          $extension)
01614   {
01615     $suite->Run($this);
01616     $report = $this->Report();
01617     if ('string' != gettype($filename))
01618     {
01619       echo $report;
01620     }
01621     else
01622     {
01623       if ('' == $filename)
01624       {
01625         $filename = tempnam(sys_get_temp_dir(), 'rep');
01626       }
01627       $filename .= '.' . $extension;
01628       $fh = fopen($filename, 'w');
01629       if (!$fh)
01630       {
01631         echo 'Unable to open file to write to: ' . $filename . "\n";
01632         return -2;
01633       }
01634       echo 'Writing results to: ' . $filename . "\n";
01635       if (!fwrite($fh, $report))
01636       {
01637         echo 'Unable to write to file: ' . $filename . "\n";
01638         return -3;
01639       }
01640       fclose($fh);      
01641     }
01642     return ($suite->AllPassed() ? 0 : -1);
01643   }
01644   
01649   public abstract function Report();
01650 }
01651 ?>
 All Data Structures Files Functions Variables

© 2011, Ed Heal