* 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…
Reference in New Issue
Block a user