Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
SuiteObjectExtractor.php
Go to the documentation of this file.
1 <?php
7 
8 use Exception;
17 
19 {
20  const SUITE_ROOT_TAG = 'suites';
21  const SUITE_TAG_NAME = 'suite';
22  const INCLUDE_TAG_NAME = 'include';
23  const EXCLUDE_TAG_NAME = 'exclude';
24  const MODULE_TAG_NAME = 'module';
25  const MODULE_TAG_FILE_ATTRIBUTE = 'file';
26  const TEST_TAG_NAME = 'test';
27  const GROUP_TAG_NAME = 'group';
28 
32  public function __construct()
33  {
34  // empty constructor
35  }
36 
47  public function parseSuiteDataIntoObjects($parsedSuiteData)
48  {
49  $suiteObjects = [];
50  $testHookObjectExtractor = new TestHookObjectExtractor();
51 
52  // make sure there are suites defined before trying to parse as objects.
53  if (!array_key_exists(self::SUITE_ROOT_TAG, $parsedSuiteData)) {
54  return $suiteObjects;
55  }
56 
57  foreach ($parsedSuiteData[self::SUITE_ROOT_TAG] as $parsedSuite) {
58  if (!is_array($parsedSuite)) {
59  // skip non array items parsed from suite (suite objects will always be arrays)
60  continue;
61  }
62 
63  // validate the name used isn't using special char or the "default" reserved name
64  NameValidationUtil::validateName($parsedSuite[self::NAME], 'Suite');
65  if ($parsedSuite[self::NAME] == 'default') {
66  throw new XmlException("A Suite can not have the name \"default\"");
67  }
68 
69  $suiteHooks = [];
70 
71  //Check for collisions between suite name and existing group name
72  $suiteName = $parsedSuite[self::NAME];
73  $testGroupConflicts = TestObjectHandler::getInstance()->getTestsByGroup($suiteName);
74  if (!empty($testGroupConflicts)) {
75  $testGroupConflictsFileNames = "";
76  foreach ($testGroupConflicts as $test) {
77  $testGroupConflictsFileNames .= $test->getFilename() . "\n";
78  }
79  $exceptionmessage = "\"Suite names and Group names can not have the same value. \t\n" .
80  "Suite: \"{$suiteName}\" also exists as a group annotation in: \n{$testGroupConflictsFileNames}";
81  throw new XmlException($exceptionmessage);
82  }
83 
84  //extract include and exclude references
85  $groupTestsToInclude = $parsedSuite[self::INCLUDE_TAG_NAME] ?? [];
86  $groupTestsToExclude = $parsedSuite[self::EXCLUDE_TAG_NAME] ?? [];
87 
88  // resolve references as test objects
89  $includeTests = $this->extractTestObjectsFromSuiteRef($groupTestsToInclude);
90  $excludeTests = $this->extractTestObjectsFromSuiteRef($groupTestsToExclude);
91 
92  // parse any object hooks
93  if (array_key_exists(TestObjectExtractor::TEST_BEFORE_HOOK, $parsedSuite)) {
94  $suiteHooks[TestObjectExtractor::TEST_BEFORE_HOOK] = $testHookObjectExtractor->extractHook(
95  $parsedSuite[self::NAME],
98  );
99  }
100  if (array_key_exists(TestObjectExtractor::TEST_AFTER_HOOK, $parsedSuite)) {
101  $suiteHooks[TestObjectExtractor::TEST_AFTER_HOOK] = $testHookObjectExtractor->extractHook(
102  $parsedSuite[self::NAME],
105  );
106  }
107 
108  if (count($suiteHooks) == 1) {
109  throw new XmlException(sprintf(
110  "Suites that contain hooks must contain both a 'before' and an 'after' hook. Suite: \"%s\"",
111  $parsedSuite[self::NAME]
112  ));
113  }
114  // check if suite hooks are empty/not included and there are no included tests/groups/modules
115  $noHooks = count($suiteHooks) == 0 ||
116  (
117  empty($suiteHooks['before']->getActions()) &&
118  empty($suiteHooks['after']->getActions())
119  );
120  // if suite body is empty throw error
121  if ($noHooks && empty($includeTests) && empty($excludeTests)) {
122  throw new XmlException(sprintf(
123  "Suites must not be empty. Suite: \"%s\"",
124  $parsedSuite[self::NAME]
125  ));
126  }
127 
128  // add all test if include tests is completely empty
129  if (empty($includeTests)) {
130  $includeTests = TestObjectHandler::getInstance()->getAllObjects();
131  }
132 
133  // create the new suite object
134  $suiteObjects[$parsedSuite[self::NAME]] = new SuiteObject(
135  $parsedSuite[self::NAME],
136  $includeTests,
137  $excludeTests,
138  $suiteHooks
139  );
140  }
141 
142  return $suiteObjects;
143  }
144 
153  private function extractTestObjectsFromSuiteRef($suiteReferences)
154  {
155  $testObjectList = [];
156  foreach ($suiteReferences as $suiteRefName => $suiteRefData) {
157  if (!is_array($suiteRefData)) {
158  continue;
159  }
160 
161  switch ($suiteRefData[self::NODE_NAME]) {
162  case self::TEST_TAG_NAME:
163  $testObject = TestObjectHandler::getInstance()->getObject($suiteRefData[self::NAME]);
164  $testObjectList[$testObject->getName()] = $testObject;
165  break;
167  $testObjectList = $testObjectList +
168  TestObjectHandler::getInstance()->getTestsByGroup($suiteRefData[self::NAME]);
169  break;
171  $testObjectList = array_merge($testObjectList, $this->extractModuleAndFiles(
172  $suiteRefData[self::NAME],
173  $suiteRefData[self::MODULE_TAG_FILE_ATTRIBUTE] ?? null
174  ));
175  break;
176  }
177  }
178 
179  return $testObjectList;
180  }
181 
190  private function extractModuleAndFiles($moduleName, $moduleFilePath)
191  {
192  if (empty($moduleFilePath)) {
193  return $this->resolveModulePathTestNames($moduleName);
194  }
195 
196  return $this->resolveFilePathTestNames($moduleFilePath, $moduleName);
197  }
198 
207  private function resolveFilePathTestNames($filename, $moduleName = null)
208  {
209  $filepath = $filename;
210  if (!strstr($filepath, DIRECTORY_SEPARATOR)) {
211  $filepath = TESTS_MODULE_PATH .
212  DIRECTORY_SEPARATOR .
213  $moduleName .
214  DIRECTORY_SEPARATOR .
215  'Test' .
216  DIRECTORY_SEPARATOR .
217  $filename;
218  }
219 
220  if (!file_exists($filepath)) {
221  throw new Exception("Could not find file ${filename}");
222  }
223 
224  $testObjects = [];
225  $xml = simplexml_load_file($filepath);
226  for ($i = 0; $i < $xml->count(); $i++) {
227  $testName = (string)$xml->test[$i]->attributes()->name;
228  $testObjects[$testName] = TestObjectHandler::getInstance()->getObject($testName);
229  }
230 
231  return $testObjects;
232  }
233 
241  private function resolveModulePathTestNames($moduleName)
242  {
243  $testObjects = [];
244  $xmlFiles = glob(
245  TESTS_MODULE_PATH .
246  DIRECTORY_SEPARATOR .
247  $moduleName .
248  DIRECTORY_SEPARATOR .
249  'Test' .
250  DIRECTORY_SEPARATOR .
251  '*.xml'
252  );
253 
254  foreach ($xmlFiles as $xmlFile) {
255  $testObjs = $this->resolveFilePathTestNames($xmlFile);
256 
257  foreach ($testObjs as $testObj) {
258  $testObjects[$testObj->getName()] = $testObj;
259  }
260  }
261 
262  return $testObjects;
263  }
264 }
$i
Definition: gallery.phtml:31