From cd6df1ffbdd096f4a4ad96d4157263aaec6118a2 Mon Sep 17 00:00:00 2001 From: tmont Date: Sat, 20 Jun 2009 05:44:02 +0000 Subject: [PATCH] * overhauled test method (now it uses closures) * implemented RecursivelyCountable in TestSuite/TestCase/TestMethod --- src/TUnit/framework/BaseTestRunner.php | 10 +++- .../framework/listeners/ConsoleListener.php | 9 +++- src/TUnit/framework/test/TestCase.php | 45 +++++++++++----- src/TUnit/framework/test/TestMethod.php | 28 ++++++---- src/TUnit/framework/test/TestSuite.php | 14 ++++- src/TUnit/framework/test/Testable.php | 6 ++- src/TUnit/util/Util.php | 51 +++++++++++++++++++ 7 files changed, 135 insertions(+), 28 deletions(-) diff --git a/src/TUnit/framework/BaseTestRunner.php b/src/TUnit/framework/BaseTestRunner.php index 0fa4600..ccf0a94 100644 --- a/src/TUnit/framework/BaseTestRunner.php +++ b/src/TUnit/framework/BaseTestRunner.php @@ -1,6 +1,6 @@ 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(); } diff --git a/src/TUnit/framework/listeners/ConsoleListener.php b/src/TUnit/framework/listeners/ConsoleListener.php index 60175a6..e0d1f96 100644 --- a/src/TUnit/framework/listeners/ConsoleListener.php +++ b/src/TUnit/framework/listeners/ConsoleListener.php @@ -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) { diff --git a/src/TUnit/framework/test/TestCase.php b/src/TUnit/framework/test/TestCase.php index 9f62d42..049cbc9 100644 --- a/src/TUnit/framework/test/TestCase.php +++ b/src/TUnit/framework/test/TestCase.php @@ -5,13 +5,16 @@ protected $name; private $autoVerify; + private $testableMethods; + const ANY = -1; const AT_LEAST_ONCE = -2; public function __construct($name) { - $this->name = $name; - $this->autoVerify = true; + $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() { - $refClass = new ReflectionClass($this); - $methods = array(); - foreach ($refClass->getMethods() as $method) { - if (preg_match('/^[\/\*\s]*@test\s*(?:\*\/)?$/m', $method->getDocComment())) { - $methods[] = $method; + public final function getTestableMethods() { + if (empty($this->testableMethods)) { + $refClass = new ReflectionClass($this); + $methods = array(); + foreach ($refClass->getMethods() as $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) { @@ -86,6 +97,14 @@ throw new FailedTest($message); } + public function count() { + return count($this->getTestableMethods()); + } + + public function getTestCount() { + return Util::countTests($this->testableMethods); + } + } ?> \ No newline at end of file diff --git a/src/TUnit/framework/test/TestMethod.php b/src/TUnit/framework/test/TestMethod.php index 2f443c0..7d27af2 100644 --- a/src/TUnit/framework/test/TestMethod.php +++ b/src/TUnit/framework/test/TestMethod.php @@ -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)); + } + } ?> \ No newline at end of file diff --git a/src/TUnit/framework/test/TestSuite.php b/src/TUnit/framework/test/TestSuite.php index dca4540..8c3cd08 100644 --- a/src/TUnit/framework/test/TestSuite.php +++ b/src/TUnit/framework/test/TestSuite.php @@ -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); + } + } ?> \ No newline at end of file diff --git a/src/TUnit/framework/test/Testable.php b/src/TUnit/framework/test/Testable.php index f9a8003..6d6c77f 100644 --- a/src/TUnit/framework/test/Testable.php +++ b/src/TUnit/framework/test/Testable.php @@ -1,6 +1,10 @@ 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; + } + } ?> \ No newline at end of file