/** * Run a test case. * * @param unittest.TestCase test * @param unittest.TestResult result * @return void * @throws lang.MethodNotImplementedException */ protected function runInternal($test, $result) { $class = $test->getClass(); $method = $class->getMethod($test->name); $this->notifyListeners('testStarted', [$test]); // Check for @ignore if ($method->hasAnnotation('ignore')) { $this->notifyListeners('testNotRun', [$result->set($test, new TestNotRun($test, new IgnoredBecause($method->getAnnotation('ignore'))))]); return; } // Check for @expect $expected = null; if ($method->hasAnnotation('expect', 'class')) { $message = $method->getAnnotation('expect', 'withMessage'); if ('' === $message || '/' === $message[0]) { $pattern = $message; } else { $pattern = '/' . preg_quote($message, '/') . '/'; } $expected = [XPClass::forName($method->getAnnotation('expect', 'class')), $pattern]; } else { if ($method->hasAnnotation('expect')) { $expected = [XPClass::forName($method->getAnnotation('expect')), null]; } } // Check for @limit $eta = 0; if ($method->hasAnnotation('limit')) { $eta = $method->getAnnotation('limit', 'time'); } // Check for @values if ($method->hasAnnotation('values')) { $annotation = $method->getAnnotation('values'); $variation = true; $values = $this->valuesFor($test, $annotation); } else { $variation = false; $values = [[]]; } // Check for @actions $actions = array_merge($this->actionsFor($class, 'unittest.TestAction'), $this->actionsFor($method, 'unittest.TestAction')); $timer = new Timer(); $report = function ($type, $outcome, $arg) use($result, $timer, &$t) { $timer->stop(); $this->notifyListeners($type, [$result->set($t, new $outcome($t, $arg, $timer->elapsedTime()))]); \xp::gc(); }; \xp::gc(); foreach ($values as $args) { $t = $variation ? new TestVariation($test, $args) : $test; $timer->start(); $tearDown = function ($test, $error) { return $error; }; try { // Before and after tests foreach ($actions as $action) { $this->invoke([$action, 'beforeTest'], $test); $tearDown = function ($test, $error) use($tearDown, $action) { $propagated = $tearDown($test, $error); try { $this->invoke([$action, 'afterTest'], $test); return $propagated; } catch (Throwable $t) { $propagated && $t->setCause($propagated); return $t; } }; } // Setup and teardown $this->invoke([$test, 'setUp'], $test); $tearDown = function ($test, $error) use($tearDown) { try { $this->invoke([$test, 'tearDown'], null); return $tearDown($test, $error); } catch (Throwable $t) { $error && $t->setCause($error); return $tearDown($test, $t); } }; // Run test $method->invoke($test, is_array($args) ? $args : [$args]); $e = $tearDown($test, null); } catch (TargetInvocationException $invoke) { $e = $tearDown($test, $invoke->getCause()); } catch (PrerequisitesNotMetError $skipped) { $tearDown($test, $skipped); $report('testSkipped', TestPrerequisitesNotMet::class, $skipped); continue; } catch (AssertionFailedError $failed) { $tearDown($test, $failed); $report('testFailed', TestAssertionFailed::class, $failed); continue; } catch (Throwable $error) { $tearDown($test, $error); $report('testError', TestError::class, $error); continue; } $timer->stop(); if ($e) { if ($expected && $expected[0]->isInstance($e)) { if ($eta && $timer->elapsedTime() > $eta) { $report('testFailed', TestAssertionFailed::class, new AssertionFailedError(new FormattedMessage('Test runtime of %.3f seconds longer than eta of %.3f seconds', [$timer->elapsedTime(), $eta]))); } else { if ($expected[1] && !preg_match($expected[1], $e->getMessage())) { $report('testFailed', TestAssertionFailed::class, new AssertionFailedError(new FormattedMessage('Expected %s\'s message "%s" differs from expected %s', [nameof($e), $e->getMessage(), $expected[1]]))); } else { if (sizeof(\xp::$errors) > 0) { $report('testWarning', TestWarning::class, $this->formatErrors(\xp::$errors)); } else { $this->notifyListeners('testSucceeded', [$result->setSucceeded($t, $timer->elapsedTime())]); } } } } else { if ($expected && !$expected[0]->isInstance($e)) { $report('testFailed', TestAssertionFailed::class, new AssertionFailedError(new FormattedMessage('Caught %s instead of expected %s', [$e->compoundMessage(), $expected[0]->getName()]))); } else { if ($e instanceof AssertionFailedError) { $report('testFailed', TestAssertionFailed::class, $e); } else { if ($e instanceof PrerequisitesNotMetError) { $report('testSkipped', TestPrerequisitesNotMet::class, $e); } else { if ($e instanceof IgnoredBecause) { $report('testSkipped', TestNotRun::class, $e); } else { $report('testError', TestError::class, $e); } } } } } } else { if ($expected) { $report('testFailed', TestAssertionFailed::class, new AssertionFailedError(new FormattedMessage('Expected %s not caught', [$expected[0]->getName()]))); } else { if (sizeof(\xp::$errors) > 0) { $report('testWarning', TestWarning::class, $this->formatErrors(\xp::$errors)); } else { if ($eta && $timer->elapsedTime() > $eta) { $report('testFailed', TestAssertionFailed::class, new AssertionFailedError(new FormattedMessage('Test runtime of %.3f seconds longer than eta of %.3f seconds', [$timer->elapsedTime(), $eta]))); } else { $this->notifyListeners('testSucceeded', [$result->setSucceeded($t, $timer->elapsedTime())]); } } } } } }
/** * Run a test case. * * @param unittest.TestCase test * @param unittest.TestResult result * @throws lang.MethodNotImplementedException */ protected function runInternal($test, $result) { $class = $test->getClass(); $method = $class->getMethod($test->name); $this->notifyListeners('testStarted', [$test]); // Check for @ignore if ($method->hasAnnotation('ignore')) { $this->notifyListeners('testNotRun', [$result->set($test, new TestNotRun($test, $method->getAnnotation('ignore')))]); return; } // Check for @expect $expected = null; if ($method->hasAnnotation('expect', 'class')) { $message = $method->getAnnotation('expect', 'withMessage'); if ('/' === $message[0]) { $pattern = $message; } else { $pattern = '/' . preg_quote($message, '/') . '/'; } $expected = [XPClass::forName($method->getAnnotation('expect', 'class')), $pattern]; } else { if ($method->hasAnnotation('expect')) { $expected = [XPClass::forName($method->getAnnotation('expect')), null]; } } // Check for @limit $eta = 0; if ($method->hasAnnotation('limit')) { $eta = $method->getAnnotation('limit', 'time'); } // Check for @values if ($method->hasAnnotation('values')) { $annotation = $method->getAnnotation('values'); $variation = true; $values = $this->valuesFor($test, $annotation); } else { $variation = false; $values = [[]]; } // Check for @actions, initialize setUp and tearDown call chains $actions = array_merge($this->actionsFor($class, 'unittest.TestAction'), $this->actionsFor($method, 'unittest.TestAction')); $setUp = function ($test) use($actions) { foreach ($actions as $action) { $action->beforeTest($test); } $test->setUp(); }; $tearDown = function ($test) use($actions) { $test->tearDown(); $raised = null; foreach ($actions as $action) { try { $action->afterTest($test); } catch (Throwable $e) { $e->setCause($raised); $raised = $e; } } if ($raised) { throw $raised; } }; $timer = new Timer(); foreach ($values as $args) { $t = $variation ? new TestVariation($test, $args) : $test; \xp::gc(); $timer->start(); // Setup test try { $setUp($test); } catch (PrerequisitesNotMetError $e) { $timer->stop(); $this->notifyListeners('testSkipped', [$result->setSkipped($t, $e, $timer->elapsedTime())]); \xp::gc(); continue; } catch (AssertionFailedError $e) { $timer->stop(); $this->notifyListeners('testFailed', [$result->setFailed($t, $e, $timer->elapsedTime())]); \xp::gc(); continue; } catch (Throwable $x) { $timer->stop(); $this->notifyListeners('testFailed', [$result->set($t, new TestError($t, $x, $timer->elapsedTime()))]); \xp::gc(); continue; } // Run test $e = null; try { $method->invoke($test, is_array($args) ? $args : [$args]); $tearDown($test); } catch (TargetInvocationException $x) { $tearDown($test); $e = $x->getCause(); } catch (Throwable $e) { // Exception inside teardown } $timer->stop(); if ($e) { if ($expected && $expected[0]->isInstance($e)) { if ($eta && $timer->elapsedTime() > $eta) { $this->notifyListeners('testFailed', [$result->setFailed($t, new AssertionFailedError(new FormattedMessage('Test runtime of %.3f seconds longer than eta of %.3f seconds', [$timer->elapsedTime(), $eta])), $timer->elapsedTime())]); } else { if ($expected[1] && !preg_match($expected[1], $e->getMessage())) { $this->notifyListeners('testFailed', [$result->setFailed($t, new AssertionFailedError(new FormattedMessage('Expected %s\'s message "%s" differs from expected %s', [nameof($e), $e->getMessage(), $expected[1]])), $timer->elapsedTime())]); } else { if (sizeof(\xp::$errors) > 0) { $this->notifyListeners('testWarning', [$result->set($t, new TestWarning($t, $this->formatErrors(\xp::$errors), $timer->elapsedTime()))]); } else { $this->notifyListeners('testSucceeded', [$result->setSucceeded($t, $timer->elapsedTime())]); } } } } else { if ($expected && !$expected[0]->isInstance($e)) { $this->notifyListeners('testFailed', [$result->setFailed($t, new AssertionFailedError(new FormattedMessage('Caught %s instead of expected %s', [$e->compoundMessage(), $expected[0]->getName()])), $timer->elapsedTime())]); } else { if ($e instanceof AssertionFailedError) { $this->notifyListeners('testFailed', [$result->setFailed($t, $e, $timer->elapsedTime())]); } else { if ($e instanceof PrerequisitesNotMetError) { $this->notifyListeners('testSkipped', [$result->setSkipped($t, $e, $timer->elapsedTime())]); } else { $this->notifyListeners('testError', [$result->set($t, new TestError($t, $e, $timer->elapsedTime()))]); } } } } \xp::gc(); continue; } else { if ($expected) { $this->notifyListeners('testFailed', [$result->setFailed($t, new AssertionFailedError(new FormattedMessage('Expected %s not caught', [$expected[0]->getName()])), $timer->elapsedTime())]); } else { if (sizeof(\xp::$errors) > 0) { $this->notifyListeners('testWarning', [$result->set($t, new TestWarning($t, $this->formatErrors(\xp::$errors), $timer->elapsedTime()))]); } else { if ($eta && $timer->elapsedTime() > $eta) { $this->notifyListeners('testFailed', [$result->setFailed($t, new AssertionFailedError('Timeout', sprintf('%.3f', $timer->elapsedTime()), sprintf('%.3f', $eta)), $timer->elapsedTime())]); } else { $this->notifyListeners('testSucceeded', [$result->setSucceeded($t, $timer->elapsedTime())]); } } } } \xp::gc(); } }
public function notCallable() { Timer::measure('@not-callable@'); }
public function not_callable_argument_passed_to_measure_7() { Timer::measure('@not-callable@'); }