Runner.php 6.2 KB

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