Skip to content

Commit da9af9a

Browse files
committed
MQE-741: two steps with same step key, the later step will overwrite the previous step.
- improve performance
1 parent dbceba1 commit da9af9a

File tree

3 files changed

+198
-2
lines changed

3 files changed

+198
-2
lines changed

etc/di.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,14 +197,14 @@
197197
<virtualType name="Magento\FunctionalTestingFramework\Config\SchemaLocator\TestData" type="Magento\FunctionalTestingFramework\Config\SchemaLocator">
198198
<arguments>
199199
<argument name="schemaPath" xsi:type="string">Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd</argument>
200-
<argument name="perFileSchema" xsi:type="string">Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd</argument>
201200
</arguments>
202201
</virtualType>
203-
<virtualType name="Magento\FunctionalTestingFramework\Config\Reader\TestData" type="Magento\FunctionalTestingFramework\Config\Reader\Filesystem">
202+
<virtualType name="Magento\FunctionalTestingFramework\Config\Reader\TestData" type="Magento\FunctionalTestingFramework\Test\Config\Reader\Filesystem">
204203
<arguments>
205204
<argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Module</argument>
206205
<argument name="converter" xsi:type="object">Magento\FunctionalTestingFramework\Config\TestDataConverter</argument>
207206
<argument name="schemaLocator" xsi:type="object">Magento\FunctionalTestingFramework\Config\SchemaLocator\TestData</argument>
207+
<argument name="domDocumentClass" xsi:type="string">Magento\FunctionalTestingFramework\Test\Config\Dom</argument>
208208
<argument name="idAttributes" xsi:type="array">
209209
<item name="/tests/test" xsi:type="string">name</item>
210210
<item name="/tests/test/remove" xsi:type="string">keyForRemoval</item>
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\FunctionalTestingFramework\Test\Config;
8+
9+
use Magento\FunctionalTestingFramework\Exceptions\XmlException;
10+
use Magento\FunctionalTestingFramework\Config\Dom\NodeMergingConfig;
11+
use Magento\FunctionalTestingFramework\Config\Dom\NodePathMatcher;
12+
13+
class Dom extends \Magento\FunctionalTestingFramework\Config\Dom
14+
{
15+
const TEST_FILE_NAME_ENDING = 'Test';
16+
const TEST_META_FILENAME_ATTRIBUTE = 'filename';
17+
const TEST_META_NAME_ATTRIBUTE = 'name';
18+
const TEST_HOOK_NAMES = ["after", "before"];
19+
20+
/**
21+
* TestDom constructor.
22+
* @param string $xml
23+
* @param string $filename
24+
* @param array $idAttributes
25+
* @param string $typeAttributeName
26+
* @param string $schemaFile
27+
* @param string $errorFormat
28+
*/
29+
public function __construct(
30+
$xml,
31+
$filename,
32+
array $idAttributes = [],
33+
$typeAttributeName = null,
34+
$schemaFile = null,
35+
$errorFormat = self::ERROR_FORMAT_DEFAULT
36+
) {
37+
$this->schemaFile = $schemaFile;
38+
$this->nodeMergingConfig = new NodeMergingConfig(new NodePathMatcher(), $idAttributes);
39+
$this->typeAttributeName = $typeAttributeName;
40+
$this->errorFormat = $errorFormat;
41+
$this->dom = $this->initDom($xml, $filename);
42+
$this->rootNamespace = $this->dom->lookupNamespaceUri($this->dom->namespaceURI);
43+
}
44+
45+
/**
46+
* Takes a dom element from xml and appends the filename based on location
47+
*
48+
* @param string $xml
49+
* @param string|null $filename
50+
* @return \DOMDocument
51+
*/
52+
public function initDom($xml, $filename = null)
53+
{
54+
$dom = parent::initDom($xml);
55+
56+
if (strpos($filename, self::TEST_FILE_NAME_ENDING)) {
57+
$testNodes = $dom->getElementsByTagName('test');
58+
foreach ($testNodes as $testNode) {
59+
/** @var \DOMElement $testNode */
60+
$testNode->setAttribute(self::TEST_META_FILENAME_ATTRIBUTE, $filename);
61+
$this->validateTestDomStepKeys($testNode, $filename);
62+
}
63+
}
64+
65+
return $dom;
66+
}
67+
68+
/**
69+
* Redirects any merges into the init method for appending xml filename
70+
*
71+
* @param string $xml
72+
* @param string|null $filename
73+
* @return void
74+
*/
75+
public function merge($xml, $filename = null)
76+
{
77+
$dom = $this->initDom($xml, $filename);
78+
$this->mergeNode($dom->documentElement, '');
79+
}
80+
81+
/**
82+
* Parses an individual DOM structure for repeated stepKey attributes
83+
*
84+
* @param \DOMElement $testNode
85+
* @param string $filename
86+
* @throws XmlException
87+
*/
88+
private function validateTestDomStepKeys($testNode, $filename)
89+
{
90+
$childNodes = $testNode->childNodes;
91+
92+
$keyValues = [];
93+
for ($i = 0; $i < $childNodes->length; $i++) {
94+
$currentNode = $childNodes->item($i);
95+
96+
if (!is_a($currentNode, \DOMElement::class)) {
97+
continue;
98+
}
99+
100+
if (in_array($currentNode->nodeName, self::TEST_HOOK_NAMES)) {
101+
$this->validateTestDomStepKeys($currentNode, $filename);
102+
}
103+
104+
if ($currentNode->hasAttribute('stepKey')) {
105+
$keyValues[] = $currentNode->getAttribute('stepKey');
106+
}
107+
}
108+
109+
$withoutDuplicates = array_unique($keyValues);
110+
$duplicates = array_diff_assoc($keyValues, $withoutDuplicates);
111+
112+
if (count($duplicates) > 0) {
113+
$stepKeyError = "";
114+
foreach ($duplicates as $duplicateKey => $duplicateValue) {
115+
$stepKeyError .= "\tstepKey: {$duplicateValue} is used more than once.\n";
116+
}
117+
118+
throw new XmlException("Tests cannot use stepKey more than once!\t\n{$stepKeyError}\tin file: {$filename}");
119+
}
120+
}
121+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\FunctionalTestingFramework\Test\Config\Reader;
8+
9+
use Magento\FunctionalTestingFramework\Util\Iterator\File;
10+
11+
class Filesystem extends \Magento\FunctionalTestingFramework\Config\Reader\Filesystem
12+
{
13+
/**
14+
* Method to redirect file name passing into Dom class
15+
*
16+
* @param File $fileList
17+
* @return array
18+
* @throws \Exception
19+
*/
20+
public function readFiles($fileList)
21+
{
22+
/** @var \Magento\FunctionalTestingFramework\Test\Config\Dom $configMerger */
23+
$configMerger = null;
24+
foreach ($fileList as $key => $content) {
25+
try {
26+
if (!$configMerger) {
27+
$configMerger = $this->createConfigMerger($this->domDocumentClass, $content, $fileList->getFilename());
28+
} else {
29+
$configMerger->merge($content, $fileList->getFilename());
30+
}
31+
} catch (\Magento\FunctionalTestingFramework\Config\Dom\ValidationException $e) {
32+
throw new \Exception("Invalid XML in file " . $key . ":\n" . $e->getMessage());
33+
}
34+
}
35+
if ($this->validationState->isValidationRequired()) {
36+
$errors = [];
37+
if ($configMerger && !$configMerger->validate($this->schemaFile, $errors)) {
38+
$message = "Invalid Document \n";
39+
throw new \Exception($message . implode("\n", $errors));
40+
}
41+
}
42+
43+
$output = [];
44+
if ($configMerger) {
45+
$output = $this->converter->convert($configMerger->getDom());
46+
}
47+
return $output;
48+
}
49+
50+
/**
51+
* Return newly created instance of a config merger
52+
*
53+
* @param string $mergerClass
54+
* @param string $initialContents
55+
* @param string $filename
56+
* @return \Magento\FunctionalTestingFramework\Config\Dom
57+
* @throws \UnexpectedValueException
58+
*/
59+
protected function createConfigMerger($mergerClass, $initialContents, $filename = null)
60+
{
61+
$result = new $mergerClass(
62+
$initialContents,
63+
$filename,
64+
$this->idAttributes,
65+
null,
66+
$this->perFileSchema
67+
);
68+
if (!$result instanceof \Magento\FunctionalTestingFramework\Config\Dom) {
69+
throw new \UnexpectedValueException(
70+
"Instance of the DOM config merger is expected, got {$mergerClass} instead."
71+
);
72+
}
73+
return $result;
74+
}
75+
}

0 commit comments

Comments
 (0)