Runner.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. namespace Codeception\PHPUnit;
  3. use Codeception\Configuration;
  4. use Codeception\Exception\ConfigurationException;
  5. use PHPUnit\Framework\TestSuite;
  6. class Runner extends \PHPUnit\TextUI\TestRunner
  7. {
  8. public static $persistentListeners = [];
  9. protected $defaultListeners = [
  10. 'xml' => false,
  11. 'phpunit-xml' => false,
  12. 'html' => false,
  13. 'tap' => false,
  14. 'json' => false,
  15. 'report' => false
  16. ];
  17. protected $config = [];
  18. protected $logDir = null;
  19. public function __construct()
  20. {
  21. $this->config = Configuration::config();
  22. $this->logDir = Configuration::outputDir(); // prepare log dir
  23. $this->phpUnitOverriders();
  24. parent::__construct();
  25. }
  26. public function phpUnitOverriders()
  27. {
  28. require_once __DIR__ . DIRECTORY_SEPARATOR . 'Overrides/Filter.php';
  29. }
  30. /**
  31. * @return null|\PHPUnit\TextUI\ResultPrinter
  32. */
  33. public function getPrinter()
  34. {
  35. return $this->printer;
  36. }
  37. public function prepareSuite(\PHPUnit\Framework\Test $suite, array &$arguments)
  38. {
  39. $this->handleConfiguration($arguments);
  40. $filterAdded = false;
  41. $filterFactory = new \PHPUnit\Runner\Filter\Factory();
  42. if ($arguments['groups']) {
  43. $filterAdded = true;
  44. $filterFactory->addFilter(
  45. new \ReflectionClass('PHPUnit\Runner\Filter\IncludeGroupFilterIterator'),
  46. $arguments['groups']
  47. );
  48. }
  49. if ($arguments['excludeGroups']) {
  50. $filterAdded = true;
  51. $filterFactory->addFilter(
  52. new \ReflectionClass('PHPUnit\Runner\Filter\ExcludeGroupFilterIterator'),
  53. $arguments['excludeGroups']
  54. );
  55. }
  56. if ($arguments['filter']) {
  57. $filterAdded = true;
  58. $filterFactory->addFilter(
  59. new \ReflectionClass('Codeception\PHPUnit\FilterTest'),
  60. $arguments['filter']
  61. );
  62. }
  63. if ($filterAdded) {
  64. $suite->injectFilter($filterFactory);
  65. }
  66. }
  67. public function doEnhancedRun(
  68. \PHPUnit\Framework\Test $suite,
  69. \PHPUnit\Framework\TestResult $result,
  70. array $arguments = []
  71. ) {
  72. unset($GLOBALS['app']); // hook for not to serialize globals
  73. $result->convertErrorsToExceptions(false);
  74. if (isset($arguments['report_useless_tests'])) {
  75. $result->beStrictAboutTestsThatDoNotTestAnything((bool)$arguments['report_useless_tests']);
  76. }
  77. if (isset($arguments['disallow_test_output'])) {
  78. $result->beStrictAboutOutputDuringTests((bool)$arguments['disallow_test_output']);
  79. }
  80. if (empty(self::$persistentListeners)) {
  81. $this->applyReporters($result, $arguments);
  82. }
  83. if (class_exists('\Symfony\Bridge\PhpUnit\SymfonyTestsListener')) {
  84. $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : [];
  85. $listener = new \Symfony\Bridge\PhpUnit\SymfonyTestsListener();
  86. $listener->globalListenerDisabled();
  87. $arguments['listeners'][] = $listener;
  88. }
  89. $arguments['listeners'][] = $this->printer;
  90. // clean up listeners between suites
  91. foreach ($arguments['listeners'] as $listener) {
  92. $result->addListener($listener);
  93. }
  94. $suite->run($result);
  95. unset($suite);
  96. foreach ($arguments['listeners'] as $listener) {
  97. $result->removeListener($listener);
  98. }
  99. return $result;
  100. }
  101. /**
  102. * @param \PHPUnit\Framework\TestResult $result
  103. * @param array $arguments
  104. *
  105. * @return array
  106. */
  107. protected function applyReporters(\PHPUnit\Framework\TestResult $result, array $arguments)
  108. {
  109. foreach ($this->defaultListeners as $listener => $value) {
  110. if (!isset($arguments[$listener])) {
  111. $arguments[$listener] = $value;
  112. }
  113. }
  114. if ($arguments['report']) {
  115. self::$persistentListeners[] = $this->instantiateReporter('report');
  116. }
  117. if ($arguments['html']) {
  118. codecept_debug('Printing HTML report into ' . $arguments['html']);
  119. self::$persistentListeners[] = $this->instantiateReporter(
  120. 'html',
  121. [$this->absolutePath($arguments['html'])]
  122. );
  123. }
  124. if ($arguments['xml']) {
  125. codecept_debug('Printing JUNIT report into ' . $arguments['xml']);
  126. self::$persistentListeners[] = $this->instantiateReporter(
  127. 'xml',
  128. [$this->absolutePath($arguments['xml']), (bool)$arguments['log_incomplete_skipped']]
  129. );
  130. }
  131. if ($arguments['phpunit-xml']) {
  132. codecept_debug('Printing PHPUNIT report into ' . $arguments['phpunit-xml']);
  133. self::$persistentListeners[] = $this->instantiateReporter(
  134. 'phpunit-xml',
  135. [$this->absolutePath($arguments['phpunit-xml']), (bool)$arguments['log_incomplete_skipped']]
  136. );
  137. }
  138. if ($arguments['tap']) {
  139. codecept_debug('Printing TAP report into ' . $arguments['tap']);
  140. self::$persistentListeners[] = $this->instantiateReporter('tap', [$this->absolutePath($arguments['tap'])]);
  141. }
  142. if ($arguments['json']) {
  143. codecept_debug('Printing JSON report into ' . $arguments['json']);
  144. self::$persistentListeners[] = $this->instantiateReporter(
  145. 'json',
  146. [$this->absolutePath($arguments['json'])]
  147. );
  148. }
  149. foreach (self::$persistentListeners as $listener) {
  150. if ($listener instanceof ConsolePrinter) {
  151. $this->printer = $listener;
  152. continue;
  153. }
  154. $result->addListener($listener);
  155. }
  156. }
  157. protected function instantiateReporter($name, $args = [])
  158. {
  159. if (!isset($this->config['reporters'][$name])) {
  160. throw new ConfigurationException("Reporter $name not defined");
  161. }
  162. return (new \ReflectionClass($this->config['reporters'][$name]))->newInstanceArgs($args);
  163. }
  164. private function absolutePath($path)
  165. {
  166. if ((strpos($path, '/') === 0) or (strpos($path, ':') === 1)) { // absolute path
  167. return $path;
  168. }
  169. return $this->logDir . $path;
  170. }
  171. }