* 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 | <?php | ||||||
| 
 | 
 | ||||||
| 	abstract class TestRunner implements Countable { | 	abstract class TestRunner implements RecursivelyCountable { | ||||||
| 		 | 		 | ||||||
| 		protected $tests; | 		protected $tests; | ||||||
| 		protected $listeners; | 		protected $listeners; | ||||||
| @ -26,6 +26,10 @@ | |||||||
| 			return $this->endTime; | 			return $this->endTime; | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
|  | 		public final function getTests() { | ||||||
|  | 			return $this->tests; | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
| 		public final function warn($message) { | 		public final function warn($message) { | ||||||
| 			foreach ($this->listeners as $listener) { | 			foreach ($this->listeners as $listener) { | ||||||
| 				$listener->onFrameworkWarning($message); | 				$listener->onFrameworkWarning($message); | ||||||
| @ -111,6 +115,10 @@ | |||||||
| 			return count($this->tests); | 			return count($this->tests); | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
|  | 		public function getTestCount() { | ||||||
|  | 			return Util::countTests($this->tests); | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
| 		protected abstract function getAllowableOptions(); | 		protected abstract function getAllowableOptions(); | ||||||
| 		 | 		 | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -41,8 +41,13 @@ | |||||||
| 		 | 		 | ||||||
| 		public function afterTestRunner(TestRunner $runner) { | 		public function afterTestRunner(TestRunner $runner) { | ||||||
| 			$elapsedTime = $runner->getEndTime() - $runner->getStartTime(); | 			$elapsedTime = $runner->getEndTime() - $runner->getStartTime(); | ||||||
| 			$numTests = (count($runner) === 1) ? '1 test' : count($runner) . ' tests'; | 			$testCount   = $runner->getTestCount(); | ||||||
| 			$this->out('Ran ' . $numTests . ' in ' . round($elapsedTime, 3) . ' seconds' . "\n"); | 			//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) { | 		public function beforeTestSuite(TestSuite $suite) { | ||||||
|  | |||||||
| @ -5,13 +5,16 @@ | |||||||
| 		protected $name; | 		protected $name; | ||||||
| 		private   $autoVerify; | 		private   $autoVerify; | ||||||
| 		 | 		 | ||||||
|  | 		private $testableMethods; | ||||||
|  | 		 | ||||||
| 		const ANY           = -1; | 		const ANY           = -1; | ||||||
| 		const AT_LEAST_ONCE = -2; | 		const AT_LEAST_ONCE = -2; | ||||||
| 		 | 		 | ||||||
| 		 | 		 | ||||||
| 		public function __construct($name) { | 		public function __construct($name) { | ||||||
| 			$this->name       = $name; | 			$this->name            = $name; | ||||||
| 			$this->autoVerify = true; | 			$this->autoVerify      = true; | ||||||
|  | 			$this->testableMethods = array(); | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		public final function getName() { | 		public final function getName() { | ||||||
| @ -26,11 +29,11 @@ | |||||||
| 			$this->autoVerify = (bool)$autoVerify; | 			$this->autoVerify = (bool)$autoVerify; | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		public function setUp() { | 		protected function setUp() { | ||||||
| 			 | 			 | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		public function tearDown() { | 		protected function tearDown() { | ||||||
| 		 | 		 | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| @ -40,9 +43,10 @@ | |||||||
| 			} | 			} | ||||||
| 			 | 			 | ||||||
| 			$result = new CombinedTestResult(); | 			$result = new CombinedTestResult(); | ||||||
| 			foreach ($this->getTestableMethods() as $method) { | 			foreach ($this->getTestableMethods() as $testMethod) { | ||||||
| 				$testMethod = new TestMethod($this, $method); | 				$this->setUp(); | ||||||
| 				$result->addTestResult($testMethod->run($listeners)); | 				$result->addTestResult($testMethod->run($listeners)); | ||||||
|  | 				$this->tearDown(); | ||||||
| 			} | 			} | ||||||
| 			 | 			 | ||||||
| 			foreach ($listeners as $listener) { | 			foreach ($listeners as $listener) { | ||||||
| @ -52,16 +56,23 @@ | |||||||
| 			return $result; | 			return $result; | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		protected final function getTestableMethods() { | 		public final function getTestableMethods() { | ||||||
| 			$refClass = new ReflectionClass($this); | 			if (empty($this->testableMethods)) { | ||||||
| 			$methods = array(); | 				$refClass = new ReflectionClass($this); | ||||||
| 			foreach ($refClass->getMethods() as $method) { | 				$methods = array(); | ||||||
| 				if (preg_match('/^[\/\*\s]*@test\s*(?:\*\/)?$/m', $method->getDocComment())) { | 				foreach ($refClass->getMethods() as $method) { | ||||||
| 					$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()); | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
|  | 				 | ||||||
|  | 				$this->testableMethods = $methods; | ||||||
| 			} | 			} | ||||||
| 			 | 			 | ||||||
| 			return $methods; | 			return $this->testableMethods; | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		protected function createMockObject($className, array $methods = array(), array $args = array(), $name = '', $callParent = true) { | 		protected function createMockObject($className, array $methods = array(), array $args = array(), $name = '', $callParent = true) { | ||||||
| @ -86,6 +97,14 @@ | |||||||
| 			throw new FailedTest($message); | 			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 { | 	/* internal */ class TestMethod implements Testable { | ||||||
| 		 | 		 | ||||||
| 		protected $testCase; | 		protected $autoVerify; | ||||||
| 		protected $method; | 		protected $closure; | ||||||
|  | 		protected $name; | ||||||
| 		 | 		 | ||||||
| 		public function __construct(TestCase $testCase, ReflectionMethod $method) { | 		public function __construct($closure, $name, $autoVerify) { | ||||||
| 			$this->testCase = $testCase; | 			$this->closure    = $closure; | ||||||
| 			$this->method   = $method; | 			$this->autoVerify = (bool)$autoVerify; | ||||||
|  | 			$this->name       = $name; | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		public function getName() { | 		public function getName() { | ||||||
| 			return $this->method->getDeclaringClass()->getName() . '::' . $this->method->getName(); | 			return $this->name; | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		public function run(array $listeners) { | 		public function run(array $listeners) { | ||||||
| @ -22,12 +24,11 @@ | |||||||
| 			$result  = null; | 			$result  = null; | ||||||
| 			$failure = null; | 			$failure = null; | ||||||
| 			 | 			 | ||||||
| 			$this->testCase->setUp(); |  | ||||||
| 			try { | 			try { | ||||||
| 				$this->method->invoke($this->testCase); | 				call_user_func($this->closure); | ||||||
| 				 | 				 | ||||||
| 				//verify if necessary
 | 				//verify if necessary
 | ||||||
| 				if ($this->testCase->getAutoVerify()) { | 				if ($this->autoVerify) { | ||||||
| 					foreach (MockRegistry::getTrackers() as $tracker) { | 					foreach (MockRegistry::getTrackers() as $tracker) { | ||||||
| 						if (!$tracker->verify()) { | 						if (!$tracker->verify()) { | ||||||
| 							throw new FailedTest('Verification of InvocationTracker failed'); | 							throw new FailedTest('Verification of InvocationTracker failed'); | ||||||
| @ -50,7 +51,6 @@ | |||||||
| 			} | 			} | ||||||
| 			 | 			 | ||||||
| 			$result = $this->createTestResult($failure); | 			$result = $this->createTestResult($failure); | ||||||
| 			$this->testCase->tearDown(); |  | ||||||
| 			 | 			 | ||||||
| 			foreach ($listeners as $listener) { | 			foreach ($listeners as $listener) { | ||||||
| 				$listener->afterTestMethod($this); | 				$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; | 			$this->tests[] = $test; | ||||||
| 			return $this; | 			return $this; | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
|  | 		public final function getTests() { | ||||||
|  | 			return $this->tests; | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
| 		public function run(array $listeners) { | 		public function run(array $listeners) { | ||||||
| 			foreach ($listeners as $listener) { | 			foreach ($listeners as $listener) { | ||||||
| 				$listener->beforeTestSuite($this); | 				$listener->beforeTestSuite($this); | ||||||
| @ -53,6 +57,14 @@ | |||||||
| 			return $result; | 			return $result; | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
|  | 		public function count() { | ||||||
|  | 			return count($this->tests); | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		public function getTestCount() { | ||||||
|  | 			return Util::countTests($this->tests); | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| ?>
 | ?>
 | ||||||
| @ -1,6 +1,10 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| 	interface Testable { | 	interface RecursivelyCountable extends Countable { | ||||||
|  | 		public function getTestCount(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	interface Testable extends RecursivelyCountable { | ||||||
| 		 | 		 | ||||||
| 		public function run(array $listeners); | 		public function run(array $listeners); | ||||||
| 		 | 		 | ||||||
|  | |||||||
| @ -86,6 +86,57 @@ | |||||||
| 			return $flattened; | 			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