PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Codeception/Lib/GroupManager.php

http://github.com/Codeception/Codeception
PHP | 169 lines | 129 code | 12 blank | 28 comment | 17 complexity | cf6decdf85e5440aeb29355fdbc7035b MD5 | raw file
  1. <?php
  2. namespace Codeception\Lib;
  3. use Codeception\Configuration;
  4. use Codeception\Exception\ConfigurationException;
  5. use Codeception\Test\Interfaces\Reported;
  6. use Codeception\Test\Descriptor;
  7. use Codeception\TestInterface;
  8. use Codeception\Test\Gherkin;
  9. use Symfony\Component\Finder\Finder;
  10. use Symfony\Component\Finder\SplFileInfo;
  11. /**
  12. * Loads information for groups from external sources (config, filesystem)
  13. */
  14. class GroupManager
  15. {
  16. protected $configuredGroups;
  17. protected $testsInGroups = [];
  18. public function __construct(array $groups)
  19. {
  20. $this->configuredGroups = $groups;
  21. $this->loadGroupsByPattern();
  22. $this->loadConfiguredGroupSettings();
  23. }
  24. /**
  25. * proceeds group names with asterisk:
  26. *
  27. * ```
  28. * "tests/_log/g_*" => [
  29. * "tests/_log/group_1",
  30. * "tests/_log/group_2",
  31. * "tests/_log/group_3",
  32. * ]
  33. * ```
  34. */
  35. protected function loadGroupsByPattern()
  36. {
  37. foreach ($this->configuredGroups as $group => $pattern) {
  38. if (strpos($group, '*') === false) {
  39. continue;
  40. }
  41. $files = Finder::create()->files()
  42. ->name(basename($pattern))
  43. ->sortByName()
  44. ->in(Configuration::projectDir().dirname($pattern));
  45. $i = 1;
  46. foreach ($files as $file) {
  47. /** @var SplFileInfo $file * */
  48. $this->configuredGroups[str_replace('*', $i, $group)] = dirname($pattern).DIRECTORY_SEPARATOR.$file->getRelativePathname();
  49. $i++;
  50. }
  51. unset($this->configuredGroups[$group]);
  52. }
  53. }
  54. protected function loadConfiguredGroupSettings()
  55. {
  56. foreach ($this->configuredGroups as $group => $tests) {
  57. $this->testsInGroups[$group] = [];
  58. if (is_array($tests)) {
  59. foreach ($tests as $test) {
  60. $file = str_replace(['/', '\\'], [DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR], $test);
  61. $this->testsInGroups[$group][] = $this->normalizeFilePath($file, $group);
  62. }
  63. } elseif (is_file(Configuration::projectDir() . $tests)) {
  64. $handle = @fopen(Configuration::projectDir() . $tests, "r");
  65. if ($handle) {
  66. while (($test = fgets($handle, 4096)) !== false) {
  67. // if the current line is blank then we need to move to the next line
  68. // otherwise the current codeception directory becomes part of the group
  69. // which causes every single test to run
  70. if (trim($test) === '') {
  71. continue;
  72. }
  73. $file = str_replace(['/', '\\'], [DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR], trim($test));
  74. $this->testsInGroups[$group][] = $this->normalizeFilePath($file, $group);
  75. }
  76. fclose($handle);
  77. }
  78. }
  79. }
  80. }
  81. /**
  82. * @param string $file
  83. * @param string $group
  84. * @return false|string
  85. * @throws ConfigurationException
  86. */
  87. private function normalizeFilePath($file, $group)
  88. {
  89. $pathParts = explode(':', $file);
  90. if (codecept_is_path_absolute($file)) {
  91. if ($file[0] === '/' && count($pathParts) > 1) {
  92. //take segment before first :
  93. $this->checkIfFileExists($pathParts[0], $group);
  94. return sprintf('%s:%s', realpath($pathParts[0]), $pathParts[1]);
  95. } else if (count($pathParts) > 2) {
  96. //on Windows take segment before second :
  97. $fullPath = $pathParts[0] . ':' . $pathParts[1];
  98. $this->checkIfFileExists($fullPath, $group);
  99. return sprintf('%s:%s', realpath($fullPath), $pathParts[2]);
  100. }
  101. $this->checkIfFileExists($file, $group);
  102. return realpath($file);
  103. } elseif (strpos($file, ':') === false) {
  104. $dirtyPath = Configuration::projectDir() . $file;
  105. $this->checkIfFileExists($dirtyPath, $group);
  106. return realpath($dirtyPath);
  107. }
  108. $dirtyPath = Configuration::projectDir() . $pathParts[0];
  109. $this->checkIfFileExists($dirtyPath, $group);
  110. return sprintf('%s:%s', realpath($dirtyPath), $pathParts[1]);
  111. }
  112. /**
  113. * @param string $path
  114. * @param string $group
  115. * @throws ConfigurationException
  116. */
  117. private function checkIfFileExists($path, $group)
  118. {
  119. if (!file_exists($path)) {
  120. throw new ConfigurationException('GroupManager: File or directory ' . $path . ' set in ' . $group. ' group does not exist');
  121. }
  122. }
  123. public function groupsForTest(\PHPUnit\Framework\Test $test)
  124. {
  125. $groups = [];
  126. $filename = Descriptor::getTestFileName($test);
  127. if ($test instanceof TestInterface) {
  128. $groups = $test->getMetadata()->getGroups();
  129. }
  130. if ($test instanceof Reported) {
  131. $info = $test->getReportFields();
  132. if (isset($info['class'])) {
  133. $groups = array_merge($groups, \PHPUnit\Util\Test::getGroups($info['class'], $info['name']));
  134. }
  135. $filename = str_replace(['\\\\', '//', '/./'], ['\\', '/', '/'], $info['file']);
  136. }
  137. if ($test instanceof \PHPUnit\Framework\TestCase) {
  138. $groups = array_merge($groups, \PHPUnit\Util\Test::getGroups(get_class($test), $test->getName(false)));
  139. }
  140. foreach ($this->testsInGroups as $group => $tests) {
  141. foreach ($tests as $testPattern) {
  142. if ($filename == $testPattern) {
  143. $groups[] = $group;
  144. }
  145. if (strpos($filename . ':' . $test->getName(false), $testPattern) === 0) {
  146. $groups[] = $group;
  147. }
  148. if ($test instanceof Gherkin
  149. && mb_strtolower($filename . ':' . $test->getMetadata()->getFeature()) === mb_strtolower($testPattern)) {
  150. $groups[] = $group;
  151. }
  152. }
  153. }
  154. return array_unique($groups);
  155. }
  156. }