* 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,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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -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…
Reference in New Issue
Block a user