Skip to content

Commit a4ac4b3

Browse files
committed
ACQE-5171: Implement a script to update Integration or WebAPI phpunit.xml file to support tests under vendor directory
1 parent 45ade72 commit a4ac4b3

File tree

1 file changed

+88
-64
lines changed

1 file changed

+88
-64
lines changed

dev/tests/utils/update-test-paths.php

Lines changed: 88 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
use Magento\Framework\Component\ComponentRegistrar;
89

@@ -14,50 +15,60 @@
1415
'USAGE',
1516
<<<USAGE
1617
Usage:
17-
php -f $scriptName path_to_phpunit.xml(.dist)
18+
php -f $scriptName path_to_phpunit.xml(.dist) rest|soap|graphql|integration
1819
USAGE
1920
);
2021

21-
assertUsage(empty($argv[1]) || !file_exists($argv[1]), 'missing or invalid phpunit.xml(.dist) file');
22-
$xmlDom = new DOMDocument();
23-
$xmlDom->preserveWhiteSpace = true;
24-
$xmlDom->formatOutput = true;
25-
assertUsage($xmlDom->load($argv[1]) == false, 'missing or invalid phpunit.xml(.dist) file');
26-
$testType = getTestType($xmlDom);
27-
// Update testsuite based on magento installation
28-
$xmlDom = updateTestSuite($xmlDom, $testType);
29-
$xmlDom->save($argv[1]);
30-
echo "{$testType} " . basename($argv[1]) . " is updated.";
22+
try {
23+
assertUsage(empty($argv[1]) || !file_exists($argv[1]), 'Invalid $argv[1]: must be a phpunit.xml(.dist) file');
24+
$xmlDom = new DOMDocument();
25+
$xmlDom->preserveWhiteSpace = true;
26+
$xmlDom->formatOutput = true;
27+
assertUsage($xmlDom->load($argv[1]) == false, 'Invalid $argv[1]: must be a phpunit.xml(.dist) file');
28+
$testType = !empty($argv[2]) ? getTestType($argv[2]) : null;
29+
assertUsage(empty($testType), 'Invalid $argv[2]: must be a value from "rest", "soap", "graphql" or "integration"');
30+
31+
// This flag allows the user to skip generating default test suite directory in result <testsuite> node.
32+
// This is desired for internal api-functional builds.
33+
$skipDefaultDir = !empty($argv[3]);
34+
35+
// Update testsuite based on magento installation
36+
$xmlDom = updateTestSuite($xmlDom, $testType);
37+
$xmlDom->save($argv[1]);
38+
//phpcs:ignore Magento2.Security.LanguageConstruct
39+
print("{$testType} " . basename($argv[1]) . " is updated.");
40+
//phpcs:ignore Magento2.Security.LanguageConstruct
41+
} catch (Exception $e) {
42+
//phpcs:ignore Magento2.Security.LanguageConstruct
43+
print($e->getMessage());
44+
//phpcs:ignore Magento2.Security.LanguageConstruct
45+
exit(1);
46+
}
3147

3248
/**
33-
* Read DOMDocument to get test type.
49+
* Parse input string to get test type.
3450
*
35-
* @param DOMDocument $dom
51+
* @param String $arg
3652
* @return string
3753
*/
38-
function getTestType(DOMDocument $dom): string
54+
function getTestType(String $arg): string
3955
{
4056
$testType = null;
41-
/** @var DOMElement $testsuite */
42-
foreach ($dom->getElementsByTagName('testsuite') as $testsuite) {
43-
if (stripos($testsuite->getAttribute('name'), 'real suite') === false) {
44-
continue;
45-
}
46-
if (stripos($testsuite->getAttribute('name'), 'rest') !== false) {
57+
switch (strtolower(trim($arg))) {
58+
case 'rest':
4759
$testType = 'REST';
48-
}
49-
if (stripos($testsuite->getAttribute('name'), 'soap') !== false) {
60+
break;
61+
case 'soap':
5062
$testType = 'SOAP';
51-
}
52-
if (stripos($testsuite->getAttribute('name'), 'graphql') !== false) {
63+
break;
64+
case 'graphql':
5365
$testType = 'GraphQl';
54-
}
55-
if (stripos($testsuite->getAttribute('name'), 'integration') !== false) {
66+
break;
67+
case 'integration':
5668
$testType = 'Integration';
57-
}
58-
if ($testType) {
5969
break;
60-
}
70+
default:
71+
break;
6172
}
6273
return $testType;
6374
}
@@ -66,7 +77,7 @@ function getTestType(DOMDocument $dom): string
6677
* Find magento modules directories patterns through magento ComponentRegistrar.
6778
*
6879
* @param string $testType
69-
* @return string []
80+
* @return array
7081
*/
7182
function findMagentoModuleDirs(string $testType): array
7283
{
@@ -80,51 +91,64 @@ function findMagentoModuleDirs(string $testType): array
8091
$magentoBaseDirPattern = preg_quote($magentoBaseDir, '/');
8192
$componentRegistrar = new ComponentRegistrar();
8293
$modulePaths = $componentRegistrar->getPaths(ComponentRegistrar::MODULE);
83-
$testPathPatterns = [];
94+
$directoryPatterns = [];
95+
$excludePatterns = [];
8496
foreach ($modulePaths as $modulePath) {
8597
preg_match('~' . $magentoBaseDirPattern . '(.+)\/[^\/]+~', $modulePath, $match);
8698
if (isset($match[1]) && isset($patterns[$testType])) {
87-
$testPathPatterns[] = '../../../' . $match[1] . '/*/Test/' . $patterns[$testType];
99+
$directoryPatterns[] = '../../../' . $match[1] . '/*/Test/' . $patterns[$testType];
88100
if ($testType == 'GraphQl') {
89-
$testPathPatterns[] = '../../../' . $match[1] . '/*GraphQl/Test/Api';
90-
$testPathPatterns[] = '../../../' . $match[1] . '/*graph-ql/Test/Api';
101+
$directoryPatterns[] = '../../../' . $match[1] . '/*GraphQl/Test/Api';
102+
$directoryPatterns[] = '../../../' . $match[1] . '/*graph-ql/Test/Api';
103+
} elseif ($testType == 'REST' || $testType == 'SOAP') {
104+
$excludePatterns[] = '../../../' . $match[1] . '/*/Test/' . $patterns['GraphQl'];
105+
$excludePatterns[] = '../../../' . $match[1] . '/*GraphQl/Test/Api';
106+
$excludePatterns[] = '../../../' . $match[1] . '/*graph-ql/Test/Api';
91107
}
92108
}
93109
}
94110

95-
return array_unique($testPathPatterns);
111+
return [
112+
'directory' => array_unique($directoryPatterns),
113+
'exclude' => array_unique($excludePatterns)
114+
];
96115
}
97116

98117
/**
99118
* Create a new testsuite DOMDocument based on installed magento module directories.
100119
*
101120
* @param string $testType
121+
* @param string $attribute
122+
* @param array $excludes
102123
* @return DOMDocument
103124
* @throws DOMException
104125
*/
105-
function createNewDomElement(string $testType): DOMDocument
126+
function createNewDomElement(string $testType, string $attribute, array $excludes): DOMDocument
106127
{
107128
$defTestSuite = getDefaultSuites($testType);
108129

109130
// Create the new element
110131
$newTestSuite = new DomDocument();
111132
$newTestSuite->formatOutput = true;
112133
$newTestSuiteElement = $newTestSuite->createElement('testsuite');
113-
if ($testType == 'Integration') {
114-
$newTestSuiteElement->setAttribute('name', 'Magento ' . $testType . ' Tests Real Suite');
115-
} else {
116-
$newTestSuiteElement->setAttribute('name', 'Magento ' . $testType . ' Web API Functional Tests Real Suite');
117-
}
134+
$newTestSuiteElement->setAttribute('name', $attribute);
118135
foreach ($defTestSuite['directory'] as $directory) {
119136
$newTestSuiteElement->appendChild($newTestSuite->createElement('directory', $directory));
120137
}
121-
foreach (findMagentoModuleDirs($testType) as $directory) {
138+
139+
$moduleDirs = findMagentoModuleDirs($testType);
140+
foreach ($moduleDirs['directory'] as $directory) {
122141
$newTestSuiteElement->appendChild($newTestSuite->createElement('directory', $directory));
123142
}
124-
foreach ($defTestSuite['exclude'] as $exclude) {
143+
foreach ($defTestSuite['exclude'] as $defExclude) {
144+
$newTestSuiteElement->appendChild($newTestSuite->createElement('exclude', $defExclude));
145+
}
146+
foreach ($moduleDirs['exclude'] as $modExclude) {
147+
$newTestSuiteElement->appendChild($newTestSuite->createElement('exclude', $modExclude));
148+
}
149+
foreach ($excludes as $exclude) {
125150
$newTestSuiteElement->appendChild($newTestSuite->createElement('exclude', $exclude));
126151
}
127-
128152
$newTestSuite->appendChild($newTestSuiteElement);
129153
return $newTestSuite;
130154
}
@@ -142,13 +166,23 @@ function updateTestSuite(DOMDocument $dom, string $testType): DOMDocument
142166
// Locate the old node
143167
$xpath = new DOMXpath($dom);
144168
$nodelist = $xpath->query('/phpunit/testsuites/testsuite');
145-
for ($index = 0; $index < $nodelist->count(); $index++) {
146-
$oldNode = $nodelist->item($index);
147-
if (stripos($oldNode->getAttribute('name'), 'real suite') !== false) {
169+
/** @var DOMNode $node */
170+
foreach ($nodelist as $node) {
171+
$attribute = $node->getAttribute('name');
172+
if (stripos($attribute, 'real') !== false) {
173+
$excludes = [];
174+
$excludeList = $node->getElementsByTagName('exclude');
175+
/** @var DOMNode $excludeNode */
176+
foreach ($excludeList as $excludeNode) {
177+
$excludes[] = $excludeNode->textContent;
178+
}
148179
// Load the $parent document fragment into the current document
149-
$newNode = $dom->importNode(createNewDomElement($testType)->documentElement, true);
180+
$newNode = $dom->importNode(
181+
createNewDomElement($testType, $attribute, $excludes)->documentElement,
182+
true
183+
);
150184
// Replace
151-
$oldNode->parentNode->replaceChild($newNode, $oldNode);
185+
$node->parentNode->replaceChild($newNode, $node);
152186
}
153187
}
154188
return $dom;
@@ -177,6 +211,8 @@ function assertUsage(bool $condition, string $error): void
177211
*/
178212
function getDefaultSuites(string $testType): array
179213
{
214+
global $skipDefaultDir;
215+
180216
$suites = [];
181217
switch ($testType) {
182218
case 'Integration':
@@ -191,29 +227,17 @@ function getDefaultSuites(string $testType): array
191227
];
192228
break;
193229
case 'REST':
194-
$suites = [
195-
'directory' => [
196-
'testsuite'
197-
],
198-
'exclude' => [
199-
'testsuite/Magento/GraphQl'
200-
]
201-
];
202-
break;
203230
case 'SOAP':
204231
$suites = [
205-
'directory' => [
206-
'testsuite'
207-
],
232+
'directory' => $skipDefaultDir ? [] : ['testsuite'],
208233
'exclude' => [
234+
'testsuite/Magento/GraphQl'
209235
]
210236
];
211237
break;
212238
case 'GraphQl':
213239
$suites = [
214-
'directory' => [
215-
'testsuite/Magento/GraphQl'
216-
],
240+
'directory' => $skipDefaultDir ? [] : ['testsuite/Magento/GraphQl'],
217241
'exclude' => [
218242
]
219243
];

0 commit comments

Comments
 (0)