PageRenderTime 38ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/codeception/base/src/Codeception/Test/Cest.php

https://bitbucket.org/vikaskr/oreazy
PHP | 216 lines | 194 code | 12 blank | 10 comment | 6 complexity | 2a572849ca4bf80ba731bcc0d11ee42d MD5 | raw file
Possible License(s): BSD-3-Clause, CC-BY-3.0, LGPL-2.1
  1. <?php
  2. namespace Codeception\Test;
  3. use Codeception\Example;
  4. use Codeception\Lib\Console\Message;
  5. use Codeception\Lib\Parser;
  6. use Codeception\Step\Comment;
  7. use Codeception\Util\Annotation;
  8. use Codeception\Util\ReflectionHelper;
  9. /**
  10. * Executes tests delivered in Cest format.
  11. *
  12. * Handles loading of Cest cases, executing specific methods, following the order from `@before` and `@after` annotations.
  13. */
  14. class Cest extends Test implements
  15. Interfaces\ScenarioDriven,
  16. Interfaces\Reported,
  17. Interfaces\Dependent,
  18. Interfaces\StrictCoverage
  19. {
  20. use Feature\ScenarioLoader;
  21. /**
  22. * @var Parser
  23. */
  24. protected $parser;
  25. protected $testClassInstance;
  26. protected $testMethod;
  27. public function __construct($testClass, $methodName, $fileName)
  28. {
  29. $metadata = new Metadata();
  30. $metadata->setName($methodName);
  31. $metadata->setFilename($fileName);
  32. $this->setMetadata($metadata);
  33. $this->testClassInstance = $testClass;
  34. $this->testMethod = $methodName;
  35. $this->createScenario();
  36. $this->parser = new Parser($this->getScenario(), $this->getMetadata());
  37. }
  38. public function preload()
  39. {
  40. $this->scenario->setFeature($this->getSpecFromMethod());
  41. $code = $this->getSourceCode();
  42. $this->parser->parseFeature($code);
  43. $this->getMetadata()->setParamsFromAnnotations(Annotation::forMethod($this->testClassInstance, $this->testMethod)->raw());
  44. $this->getMetadata()->getService('di')->injectDependencies($this->testClassInstance);
  45. // add example params to feature
  46. if ($this->getMetadata()->getCurrent('example')) {
  47. $step = new Comment('', $this->getMetadata()->getCurrent('example'));
  48. $this->getScenario()->setFeature($this->getScenario()->getFeature() . ' | '. $step->getArgumentsAsString(100));
  49. }
  50. }
  51. public function getSourceCode()
  52. {
  53. $method = new \ReflectionMethod($this->testClassInstance, $this->testMethod);
  54. $start_line = $method->getStartLine() - 1; // it's actually - 1, otherwise you wont get the function() block
  55. $end_line = $method->getEndLine();
  56. $source = file($method->getFileName());
  57. return implode("", array_slice($source, $start_line, $end_line - $start_line));
  58. }
  59. public function getSpecFromMethod()
  60. {
  61. $text = $this->testMethod;
  62. $text = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\\1 \\2', $text);
  63. $text = preg_replace('/([a-z\d])([A-Z])/', '\\1 \\2', $text);
  64. $text = strtolower($text);
  65. return $text;
  66. }
  67. public function test()
  68. {
  69. $actorClass = $this->getMetadata()->getCurrent('actor');
  70. $I = new $actorClass($this->getScenario());
  71. try {
  72. $this->executeHook($I, 'before');
  73. $this->executeBeforeMethods($this->testMethod, $I);
  74. $this->executeTestMethod($I);
  75. $this->executeAfterMethods($this->testMethod, $I);
  76. $this->executeHook($I, 'after');
  77. } catch (\Exception $e) {
  78. $this->executeHook($I, 'failed');
  79. // fails and errors are now handled by Codeception\PHPUnit\Listener
  80. throw $e;
  81. }
  82. }
  83. protected function executeHook($I, $hook)
  84. {
  85. if (is_callable([$this->testClassInstance, "_$hook"])) {
  86. $this->invoke("_$hook", [$I, $this->scenario]);
  87. }
  88. }
  89. protected function executeBeforeMethods($testMethod, $I)
  90. {
  91. $annotations = \PHPUnit_Util_Test::parseTestMethodAnnotations(get_class($this->testClassInstance), $testMethod);
  92. if (!empty($annotations['method']['before'])) {
  93. foreach ($annotations['method']['before'] as $m) {
  94. $this->executeContextMethod(trim($m), $I);
  95. }
  96. }
  97. }
  98. protected function executeAfterMethods($testMethod, $I)
  99. {
  100. $annotations = \PHPUnit_Util_Test::parseTestMethodAnnotations(get_class($this->testClassInstance), $testMethod);
  101. if (!empty($annotations['method']['after'])) {
  102. foreach ($annotations['method']['after'] as $m) {
  103. $this->executeContextMethod(trim($m), $I);
  104. }
  105. }
  106. }
  107. protected function executeContextMethod($context, $I)
  108. {
  109. if (method_exists($this->testClassInstance, $context)) {
  110. $this->executeBeforeMethods($context, $I);
  111. $this->invoke($context, [$I, $this->scenario]);
  112. $this->executeAfterMethods($context, $I);
  113. return;
  114. }
  115. throw new \LogicException(
  116. "Method $context defined in annotation but does not exist in " . get_class($this->testClassInstance)
  117. );
  118. }
  119. protected function invoke($methodName, array $context)
  120. {
  121. foreach ($context as $class) {
  122. $this->getMetadata()->getService('di')->set($class);
  123. }
  124. $this->getMetadata()->getService('di')->injectDependencies($this->testClassInstance, $methodName, $context);
  125. }
  126. protected function executeTestMethod($I)
  127. {
  128. if (!method_exists($this->testClassInstance, $this->testMethod)) {
  129. throw new \Exception("Method {$this->testMethod} can't be found in tested class");
  130. }
  131. if ($this->getMetadata()->getCurrent('example')) {
  132. $this->invoke($this->testMethod, [$I, $this->scenario, new Example($this->getMetadata()->getCurrent('example'))]);
  133. return;
  134. }
  135. $this->invoke($this->testMethod, [$I, $this->scenario]);
  136. }
  137. public function toString()
  138. {
  139. return sprintf('%s: %s', ReflectionHelper::getClassShortName($this->getTestClass()), Message::ucfirst($this->getFeature()));
  140. }
  141. public function getSignature()
  142. {
  143. return get_class($this->getTestClass()) . ":" . $this->getTestMethod();
  144. }
  145. public function getTestClass()
  146. {
  147. return $this->testClassInstance;
  148. }
  149. public function getTestMethod()
  150. {
  151. return $this->testMethod;
  152. }
  153. /**
  154. * @return array
  155. */
  156. public function getReportFields()
  157. {
  158. return [
  159. 'file' => $this->getFileName(),
  160. 'name' => $this->getTestMethod(),
  161. 'class' => get_class($this->getTestClass()),
  162. 'feature' => $this->getFeature()
  163. ];
  164. }
  165. protected function getParser()
  166. {
  167. return $this->parser;
  168. }
  169. public function getDependencies()
  170. {
  171. $names = [];
  172. foreach ($this->getMetadata()->getDependencies() as $required) {
  173. if ((strpos($required, ':') === false) and method_exists($this->getTestClass(), $required)) {
  174. $required = get_class($this->getTestClass()) . ":$required";
  175. }
  176. $names[] = $required;
  177. }
  178. return $names;
  179. }
  180. public function getLinesToBeCovered()
  181. {
  182. $class = get_class($this->getTestClass());
  183. $method = $this->getTestMethod();
  184. return \PHPUnit_Util_Test::getLinesToBeCovered($class, $method);
  185. }
  186. public function getLinesToBeUsed()
  187. {
  188. $class = get_class($this->getTestClass());
  189. $method = $this->getTestMethod();
  190. return \PHPUnit_Util_Test::getLinesToBeUsed($class, $method);
  191. }
  192. }