/** * Runs the test case. * @return void */ public function run($method = NULL) { $rc = new \ReflectionClass($this); $methods = $method ? array($rc->getMethod($method)) : $rc->getMethods(\ReflectionMethod::IS_PUBLIC); foreach ($methods as $method) { if (!preg_match('#^test[A-Z]#', $method->getName())) { continue; } $data = array(); $info = Helpers::parseDocComment($method->getDocComment()) + array('dataprovider' => NULL, 'throws' => NULL); if ($info['throws'] === '') { throw new TestCaseException("Missing class name in @throws annotation for {$method->getName()}()."); } elseif (is_array($info['throws'])) { throw new TestCaseException("Annotation @throws for {$method->getName()}() can be specified only once."); } else { $throws = preg_split('#\\s+#', $info['throws'], 2) + array(NULL, NULL); } foreach ((array) $info['dataprovider'] as $provider) { $res = $this->getData($provider); if (!is_array($res)) { throw new TestCaseException("Data provider {$provider}() doesn't return array."); } $data = array_merge($data, $res); } if (!$info['dataprovider']) { if ($method->getNumberOfRequiredParameters()) { throw new TestCaseException("Method {$method->getName()}() has arguments, but @dataProvider is missing."); } $data[] = array(); } foreach ($data as $args) { try { if ($info['throws']) { $tmp = $this; $e = Assert::error(function () use($tmp, $method, $args) { $tmp->runTest($method->getName(), $args); }, $throws[0], $throws[1]); if ($e instanceof AssertException) { throw $e; } } else { $this->runTest($method->getName(), $args); } } catch (AssertException $e) { $e->message .= " in {$method->getName()}" . substr(Dumper::toLine($args), 5); throw $e; } } } }
/** * Runs the test method. * @return void */ private function runMethod($method) { $method = new \ReflectionMethod($this, $method); if (!$method->isPublic()) { throw new TestCaseException("Method {$method->getName()} is not public. Make it public or rename it."); } $data = array(); $info = Helpers::parseDocComment($method->getDocComment()) + array('dataprovider' => NULL, 'throws' => NULL); if ($info['throws'] === '') { throw new TestCaseException("Missing class name in @throws annotation for {$method->getName()}()."); } elseif (is_array($info['throws'])) { throw new TestCaseException("Annotation @throws for {$method->getName()}() can be specified only once."); } else { $throws = preg_split('#\\s+#', $info['throws'], 2) + array(NULL, NULL); } foreach ((array) $info['dataprovider'] as $provider) { $res = $this->getData($provider); if (!is_array($res)) { throw new TestCaseException("Data provider {$provider}() doesn't return array."); } $data = array_merge($data, $res); } if (!$info['dataprovider']) { if ($method->getNumberOfRequiredParameters()) { throw new TestCaseException("Method {$method->getName()}() has arguments, but @dataProvider is missing."); } $data[] = array(); } foreach ($data as $args) { try { if ($info['throws']) { $tmp = $this; $e = Assert::error(function () use($tmp, $method, $args) { $tmp->runTest($method->getName(), $args); }, $throws[0], $throws[1]); if ($e instanceof AssertException) { throw $e; } } else { $this->runTest($method->getName(), $args); } } catch (AssertException $e) { throw $e->setMessage("{$e->origMessage} in {$method->getName()}" . substr(Dumper::toLine($args), 5)); } } }
/** * @param mixed $value * @param string $name * @param int $code * @param string $error * @param string $level * @return Assert */ function Validate($value, $name = '', $code = 0, $error = '', $level = Assert::WARNING) { $assert = new Assert($value); $assert->setExceptionClass('Terah\\Assert\\ValidationFailedException'); if ($name) { $assert->name($name); } if ($code) { $assert->code($code); } if ($error) { $assert->error($error); } if ($level) { $assert->level($level); } return $assert; }
/** * Runs the test method. * @param string test method name * @param array test method parameters (dataprovider bypass) * @return void */ public function runTest($method, array $args = NULL) { $method = new \ReflectionMethod($this, $method); if (!$method->isPublic()) { throw new TestCaseException("Method {$method->getName()} is not public. Make it public or rename it."); } $info = Helpers::parseDocComment($method->getDocComment()) + array('dataprovider' => NULL, 'throws' => NULL); if ($info['throws'] === '') { throw new TestCaseException("Missing class name in @throws annotation for {$method->getName()}()."); } elseif (is_array($info['throws'])) { throw new TestCaseException("Annotation @throws for {$method->getName()}() can be specified only once."); } else { $throws = preg_split('#\\s+#', $info['throws'], 2) + array(NULL, NULL); } $data = array(); if ($args === NULL) { $defaultParams = array(); foreach ($method->getParameters() as $param) { $defaultParams[$param->getName()] = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : NULL; } foreach ((array) $info['dataprovider'] as $provider) { $res = $this->getData($provider); if (!is_array($res)) { throw new TestCaseException("Data provider {$provider}() doesn't return array."); } foreach ($res as $set) { $data[] = is_string(key($set)) ? array_merge($defaultParams, $set) : $set; } } if (!$info['dataprovider']) { if ($method->getNumberOfRequiredParameters()) { throw new TestCaseException("Method {$method->getName()}() has arguments, but @dataProvider is missing."); } $data[] = array(); } } else { $data[] = $args; } $me = $this; $errorHandler = function () use($me, &$prev) { restore_error_handler(); $rm = new \ReflectionMethod($me, 'tearDown'); $rm->setAccessible(TRUE); set_error_handler(function () { }); // mute all errors $rm->invoke($me); restore_error_handler(); return $prev ? call_user_func_array($prev, func_get_args()) : FALSE; }; foreach ($data as $params) { try { $this->setUp(); $prev = set_error_handler($errorHandler); try { if ($info['throws']) { $tmp = $this; $e = Assert::error(function () use($tmp, $method, $params) { call_user_func_array(array($tmp, $method->getName()), $params); }, $throws[0], $throws[1]); if ($e instanceof AssertException) { throw $e; } } else { call_user_func_array(array($this, $method->getName()), $params); } } catch (\Exception $testException) { } restore_error_handler(); try { $this->tearDown(); } catch (\Exception $tearDownException) { } if (isset($testException)) { throw $testException; } elseif (isset($tearDownException)) { throw $tearDownException; } } catch (AssertException $e) { throw $e->setMessage("{$e->origMessage} in {$method->getName()}" . substr(Dumper::toLine($params), 5)); } } }
/** * Runs the test method. * @param string test method name * @param array test method parameters (dataprovider bypass) * @return void */ public function runTest($method, array $args = NULL) { if (!method_exists($this, $method)) { throw new TestCaseException("Method '{$method}' does not exist."); } elseif (!preg_match(self::METHOD_PATTERN, $method)) { throw new TestCaseException("Method '{$method}' is not a testing method."); } $method = new \ReflectionMethod($this, $method); if (!$method->isPublic()) { throw new TestCaseException("Method {$method->getName()} is not public. Make it public or rename it."); } $info = Helpers::parseDocComment($method->getDocComment()) + ['dataprovider' => NULL, 'throws' => NULL]; if ($info['throws'] === '') { throw new TestCaseException("Missing class name in @throws annotation for {$method->getName()}()."); } elseif (is_array($info['throws'])) { throw new TestCaseException("Annotation @throws for {$method->getName()}() can be specified only once."); } else { $throws = preg_split('#\\s+#', $info['throws'], 2) + [NULL, NULL]; } $data = []; if ($args === NULL) { $defaultParams = []; foreach ($method->getParameters() as $param) { $defaultParams[$param->getName()] = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : NULL; } foreach ((array) $info['dataprovider'] as $provider) { $res = $this->getData($provider); if (!is_array($res) && !$res instanceof \Traversable) { throw new TestCaseException("Data provider {$provider}() doesn't return array or Traversable."); } foreach ($res as $set) { $data[] = is_string(key($set)) ? array_merge($defaultParams, $set) : $set; } } if (!$info['dataprovider']) { if ($method->getNumberOfRequiredParameters()) { throw new TestCaseException("Method {$method->getName()}() has arguments, but @dataProvider is missing."); } $data[] = []; } } else { $data[] = $args; } if ($this->prevErrorHandler === FALSE) { $this->prevErrorHandler = set_error_handler(function ($severity) { if ($this->handleErrors && ($severity & error_reporting()) === $severity) { $this->handleErrors = FALSE; $this->silentTearDown(); } return $this->prevErrorHandler ? call_user_func_array($this->prevErrorHandler, func_get_args()) : FALSE; }); } foreach ($data as $params) { try { $this->setUp(); $this->handleErrors = TRUE; try { if ($info['throws']) { $e = Assert::error(function () use($method, $params) { call_user_func_array([$this, $method->getName()], $params); }, $throws[0], $throws[1]); if ($e instanceof AssertException) { throw $e; } } else { call_user_func_array([$this, $method->getName()], $params); } } catch (\Exception $e) { $this->handleErrors = FALSE; $this->silentTearDown(); throw $e; } $this->handleErrors = FALSE; $this->tearDown(); } catch (AssertException $e) { throw $e->setMessage("{$e->origMessage} in {$method->getName()}(" . substr(Dumper::toLine($params), 1, -1) . ')'); } } }