* overhauled test method (now it uses closures)
* implemented RecursivelyCountable in TestSuite/TestCase/TestMethod
This commit is contained in:
		
							parent
							
								
									b4837595ee
								
							
						
					
					
						commit
						cd6df1ffbd
					
				| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| 	abstract class TestRunner implements Countable { | ||||
| 	abstract class TestRunner implements RecursivelyCountable { | ||||
| 		 | ||||
| 		protected $tests; | ||||
| 		protected $listeners; | ||||
| @ -26,6 +26,10 @@ | ||||
| 			return $this->endTime; | ||||
| 		} | ||||
| 		 | ||||
| 		public final function getTests() { | ||||
| 			return $this->tests; | ||||
| 		} | ||||
| 		 | ||||
| 		public final function warn($message) { | ||||
| 			foreach ($this->listeners as $listener) { | ||||
| 				$listener->onFrameworkWarning($message); | ||||
| @ -111,6 +115,10 @@ | ||||
| 			return count($this->tests); | ||||
| 		} | ||||
| 		 | ||||
| 		public function getTestCount() { | ||||
| 			return Util::countTests($this->tests); | ||||
| 		} | ||||
| 		 | ||||
| 		protected abstract function getAllowableOptions(); | ||||
| 		 | ||||
| 	} | ||||
|  | ||||
| @ -41,8 +41,13 @@ | ||||
| 		 | ||||
| 		public function afterTestRunner(TestRunner $runner) { | ||||
| 			$elapsedTime = $runner->getEndTime() - $runner->getStartTime(); | ||||
| 			$numTests = (count($runner) === 1) ? '1 test' : count($runner) . ' tests'; | ||||
| 			$this->out('Ran ' . $numTests . ' in ' . round($elapsedTime, 3) . ' seconds' . "\n"); | ||||
| 			$testCount   = $runner->getTestCount(); | ||||
| 			//print_r($runner->getTests());
 | ||||
| 			$suites      = $testCount['suite'] === 1  ? '1 test suite'  : $testCount['suite'] . ' test suites'; | ||||
| 			$cases       = $testCount['case'] === 1   ? '1 test case'   : $testCount['case']  . ' test cases'; | ||||
| 			$methods     = $testCount['method'] === 1 ? '1 test method' : $testCount['method'] . ' test methods'; | ||||
| 			 | ||||
| 			$this->out("Ran $suites, $cases and $methods in " . round($elapsedTime, 3) . ' seconds' . "\n"); | ||||
| 		} | ||||
| 		 | ||||
| 		public function beforeTestSuite(TestSuite $suite) { | ||||
|  | ||||
| @ -5,6 +5,8 @@ | ||||
| 		protected $name; | ||||
| 		private   $autoVerify; | ||||
| 		 | ||||
| 		private $testableMethods; | ||||
| 		 | ||||
| 		const ANY           = -1; | ||||
| 		const AT_LEAST_ONCE = -2; | ||||
| 		 | ||||
| @ -12,6 +14,7 @@ | ||||
| 		public function __construct($name) { | ||||
| 			$this->name            = $name; | ||||
| 			$this->autoVerify      = true; | ||||
| 			$this->testableMethods = array(); | ||||
| 		} | ||||
| 		 | ||||
| 		public final function getName() { | ||||
| @ -26,11 +29,11 @@ | ||||
| 			$this->autoVerify = (bool)$autoVerify; | ||||
| 		} | ||||
| 		 | ||||
| 		public function setUp() { | ||||
| 		protected function setUp() { | ||||
| 			 | ||||
| 		} | ||||
| 		 | ||||
| 		public function tearDown() { | ||||
| 		protected function tearDown() { | ||||
| 		 | ||||
| 		} | ||||
| 		 | ||||
| @ -40,9 +43,10 @@ | ||||
| 			} | ||||
| 			 | ||||
| 			$result = new CombinedTestResult(); | ||||
| 			foreach ($this->getTestableMethods() as $method) { | ||||
| 				$testMethod = new TestMethod($this, $method); | ||||
| 			foreach ($this->getTestableMethods() as $testMethod) { | ||||
| 				$this->setUp(); | ||||
| 				$result->addTestResult($testMethod->run($listeners)); | ||||
| 				$this->tearDown(); | ||||
| 			} | ||||
| 			 | ||||
| 			foreach ($listeners as $listener) { | ||||
| @ -52,16 +56,23 @@ | ||||
| 			return $result; | ||||
| 		} | ||||
| 		 | ||||
| 		protected final function getTestableMethods() { | ||||
| 		public final function getTestableMethods() { | ||||
| 			if (empty($this->testableMethods)) { | ||||
| 				$refClass = new ReflectionClass($this); | ||||
| 				$methods = array(); | ||||
| 				foreach ($refClass->getMethods() as $method) { | ||||
| 				if (preg_match('/^[\/\*\s]*@test\s*(?:\*\/)?$/m', $method->getDocComment())) { | ||||
| 					$methods[] = $method; | ||||
| 					if ( | ||||
| 						$method->getDeclaringClass()->getName() !== __CLASS__ && | ||||
| 						preg_match('/^[\/\*\s]*@test\s*(?:\*\/)?$/m', $method->getDocComment()) | ||||
| 					) { | ||||
| 						$methods[] = new TestMethod(Util::getClosure($this, $method->getName()), get_class($this) . '::' . $method->getName(), $this->getAutoVerify()); | ||||
| 					} | ||||
| 				} | ||||
| 				 | ||||
| 			return $methods; | ||||
| 				$this->testableMethods = $methods; | ||||
| 			} | ||||
| 			 | ||||
| 			return $this->testableMethods; | ||||
| 		} | ||||
| 		 | ||||
| 		protected function createMockObject($className, array $methods = array(), array $args = array(), $name = '', $callParent = true) { | ||||
| @ -86,6 +97,14 @@ | ||||
| 			throw new FailedTest($message); | ||||
| 		} | ||||
| 		 | ||||
| 		public function count() { | ||||
| 			return count($this->getTestableMethods()); | ||||
| 		} | ||||
| 		 | ||||
| 		public function getTestCount() { | ||||
| 			return Util::countTests($this->testableMethods); | ||||
| 		} | ||||
| 		 | ||||
| 	} | ||||
| 
 | ||||
| ?>
 | ||||
| @ -2,16 +2,18 @@ | ||||
| 
 | ||||
| 	/* internal */ class TestMethod implements Testable { | ||||
| 		 | ||||
| 		protected $testCase; | ||||
| 		protected $method; | ||||
| 		protected $autoVerify; | ||||
| 		protected $closure; | ||||
| 		protected $name; | ||||
| 		 | ||||
| 		public function __construct(TestCase $testCase, ReflectionMethod $method) { | ||||
| 			$this->testCase = $testCase; | ||||
| 			$this->method   = $method; | ||||
| 		public function __construct($closure, $name, $autoVerify) { | ||||
| 			$this->closure    = $closure; | ||||
| 			$this->autoVerify = (bool)$autoVerify; | ||||
| 			$this->name       = $name; | ||||
| 		} | ||||
| 		 | ||||
| 		public function getName() { | ||||
| 			return $this->method->getDeclaringClass()->getName() . '::' . $this->method->getName(); | ||||
| 			return $this->name; | ||||
| 		} | ||||
| 		 | ||||
| 		public function run(array $listeners) { | ||||
| @ -22,12 +24,11 @@ | ||||
| 			$result  = null; | ||||
| 			$failure = null; | ||||
| 			 | ||||
| 			$this->testCase->setUp(); | ||||
| 			try { | ||||
| 				$this->method->invoke($this->testCase); | ||||
| 				call_user_func($this->closure); | ||||
| 				 | ||||
| 				//verify if necessary
 | ||||
| 				if ($this->testCase->getAutoVerify()) { | ||||
| 				if ($this->autoVerify) { | ||||
| 					foreach (MockRegistry::getTrackers() as $tracker) { | ||||
| 						if (!$tracker->verify()) { | ||||
| 							throw new FailedTest('Verification of InvocationTracker failed'); | ||||
| @ -50,7 +51,6 @@ | ||||
| 			} | ||||
| 			 | ||||
| 			$result = $this->createTestResult($failure); | ||||
| 			$this->testCase->tearDown(); | ||||
| 			 | ||||
| 			foreach ($listeners as $listener) { | ||||
| 				$listener->afterTestMethod($this); | ||||
| @ -92,6 +92,14 @@ | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		public function count() { | ||||
| 			return 1; | ||||
| 		} | ||||
| 		 | ||||
| 		public function getTestCount() { | ||||
| 			return Util::countTests(array($this)); | ||||
| 		} | ||||
| 		 | ||||
| 	} | ||||
| 
 | ||||
| ?>
 | ||||
| @ -22,11 +22,15 @@ | ||||
| 		 | ||||
| 		} | ||||
| 		 | ||||
| 		public function addTest(Testable $test) { | ||||
| 		public final function addTest(Testable $test) { | ||||
| 			$this->tests[] = $test; | ||||
| 			return $this; | ||||
| 		} | ||||
| 		 | ||||
| 		public final function getTests() { | ||||
| 			return $this->tests; | ||||
| 		} | ||||
| 		 | ||||
| 		public function run(array $listeners) { | ||||
| 			foreach ($listeners as $listener) { | ||||
| 				$listener->beforeTestSuite($this); | ||||
| @ -53,6 +57,14 @@ | ||||
| 			return $result; | ||||
| 		} | ||||
| 		 | ||||
| 		public function count() { | ||||
| 			return count($this->tests); | ||||
| 		} | ||||
| 		 | ||||
| 		public function getTestCount() { | ||||
| 			return Util::countTests($this->tests); | ||||
| 		} | ||||
| 		 | ||||
| 	} | ||||
| 
 | ||||
| ?>
 | ||||
| @ -1,6 +1,10 @@ | ||||
| <?php | ||||
| 
 | ||||
| 	interface Testable { | ||||
| 	interface RecursivelyCountable extends Countable { | ||||
| 		public function getTestCount(); | ||||
| 	} | ||||
| 
 | ||||
| 	interface Testable extends RecursivelyCountable { | ||||
| 		 | ||||
| 		public function run(array $listeners); | ||||
| 		 | ||||
|  | ||||
| @ -86,6 +86,57 @@ | ||||
| 			return $flattened; | ||||
| 		} | ||||
| 		 | ||||
| 		public static function countTests(array $tests) { | ||||
| 			$counts = array( | ||||
| 				'suite'  => 0, | ||||
| 				'case'   => 0, | ||||
| 				'method' => 0 | ||||
| 			); | ||||
| 			 | ||||
| 			foreach ($tests as $test) { | ||||
| 				if ($test instanceof TestSuite) { | ||||
| 					$counts['suite']++; | ||||
| 					$counts = self::mergeTestCount($counts, self::countTests($test->getTests())); | ||||
| 				} else if ($test instanceof TestCase) { | ||||
| 					$counts['case']++; | ||||
| 					$counts = self::mergeTestCount($counts, self::countTests($test->getTestableMethods())); | ||||
| 				} else if ($test instanceof TestMethod) { | ||||
| 					$counts['method']++; | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			return $counts; | ||||
| 		} | ||||
| 		 | ||||
| 		private static function mergeTestCount(array $arr1, array $arr2) { | ||||
| 			$arr1['suite']  += $arr2['suite']; | ||||
| 			$arr1['case']   += $arr2['case']; | ||||
| 			$arr1['method'] += $arr2['method']; | ||||
| 			return $arr1; | ||||
| 		} | ||||
| 		 | ||||
| 		public static function getClosure($object, $method) { | ||||
| 			if (!is_object($object)) { | ||||
| 				throw new InvalidArgumentException('1st argument must be an object'); | ||||
| 			} | ||||
| 			 | ||||
| 			$closure = create_function('', | ||||
| 			' | ||||
| 				$args = func_get_args(); | ||||
| 				static $obj = null; | ||||
| 				 | ||||
| 				if ($obj === null && isset($args[0]) && is_object($args[0])) { | ||||
| 					$obj = $args[0]; | ||||
| 					return; | ||||
| 				} | ||||
| 				 | ||||
| 				return call_user_func_array(array($obj, \'' . $method . '\'), $args);' | ||||
| 			); | ||||
| 			 | ||||
| 			$closure($object); | ||||
| 			return $closure; | ||||
| 		} | ||||
| 		 | ||||
| 	} | ||||
| 
 | ||||
| ?>
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user