Skip to content

Commit 7a26513

Browse files
committed
Merge remote-tracking branch 'origin/develop' into MQE-2141
2 parents aea82ab + 64e7788 commit 7a26513

17 files changed

+184
-59
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ dev/tests/mftf.log
1919
dev/tests/docs/*
2020
dev/tests/_output
2121
dev/tests/functional.suite.yml
22-
mftf-annotations-static-check.txt
22+

CHANGELOG.md

+19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
Magento Functional Testing Framework Changelog
22
================================================
3+
3.0.0 RC3
4+
---------
5+
6+
### Enhancements
7+
8+
* Maintainability
9+
* Added support for Two-Factor Authentication (2FA). [See configure-2fa page for details](./docs/configure-2fa.md)
10+
* Added new static check `annotationsCheck` that checks and reports missing annotations in tests.
11+
* Updated `mftf static-checks` command to allow executing static-checks defined in `staticRuleSet.json` by default. [See command page for details](./docs/commands/mftf.md#static-checks)
12+
* Added new upgrade script to remove unused arguments from action groups.
13+
* Added unhandledPromptBehavior driver capability for Chrome 75+ support.
14+
* Removed redundant and unused classes.
15+
16+
### Fixes
17+
18+
* Fixed issue with custom helper usage in suites.
19+
* Fixed issue with decryption of secrets during data entity creation.
20+
* Fixed issue with merging of `array` items in data entity.
21+
322
3.0.0 RC2
423
---------
524

docs/commands/mftf.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -430,13 +430,15 @@ The example parameters are taken from the `etc/config/.env.example` file.
430430

431431
### `static-checks`
432432

433-
Runs all or specific MFTF static-checks on the test codebase that MFTF is currently attached to.
433+
Runs all or specific MFTF static-checks on the test codebase that MFTF is currently attached to.
434434
Behavior for determining what tests to run is as follows:
435435

436436
* If test names are specified, only those tests are run.
437437
* If no test names are specified, tests are run according to `staticRuleset.json`.
438438
* If no `staticRuleset.json` is found, all tests are run.
439439

440+
Static checks errors are written to *.txt files under TEST_BP/tests/_output/static-results/
441+
440442
#### Usage
441443

442444
```bash

etc/config/functional.suite.dist.yml

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ modules:
1616
- \Magento\FunctionalTestingFramework\Module\MagentoAssert
1717
- \Magento\FunctionalTestingFramework\Module\MagentoActionProxies
1818
- Asserts
19+
- \Magento\FunctionalTestingFramework\Helper\HelperContainer
1920
config:
2021
\Magento\FunctionalTestingFramework\Module\MagentoWebDriver:
2122
url: "%MAGENTO_BASE_URL%"
@@ -34,5 +35,6 @@ modules:
3435
protocol: "%SELENIUM_PROTOCOL%"
3536
path: "%SELENIUM_PATH%"
3637
capabilities:
37-
chromeOptions:
38-
args: ["--window-size=1280,1024", "--disable-extensions", "--enable-automation", "--disable-gpu", "--enable-Passthrough"]
38+
unhandledPromptBehavior: "ignore"
39+
chromeOptions:
40+
args: ["--window-size=1280,1024", "--disable-extensions", "--enable-automation", "--disable-gpu", "--enable-Passthrough", "--disable-dev-shm-usage"]

src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php

+27-11
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,6 @@ public function createEntity(
8686
foreach ($dependentObjectKeys as $objectKey) {
8787
$retrievedDependentObjects[] = $this->retrieveEntity($objectKey, $scope);
8888
}
89-
90-
foreach ($overrideFields as $index => $field) {
91-
try {
92-
$decrptedField = CredentialStore::getInstance()->decryptAllSecretsInString($field);
93-
if ($decrptedField !== false) {
94-
$overrideFields[$index] = $decrptedField;
95-
}
96-
} catch (TestFrameworkException $e) {
97-
//catch exception if Credentials are not defined
98-
}
99-
}
10089

10190
$retrievedEntity = DataObjectHandler::getInstance()->getObject($entity);
10291

@@ -107,6 +96,8 @@ public function createEntity(
10796
);
10897
}
10998

99+
$overrideFields = $this->resolveOverrideFields($overrideFields);
100+
110101
$persistedObject = new DataPersistenceHandler(
111102
$retrievedEntity,
112103
$retrievedDependentObjects,
@@ -262,4 +253,29 @@ public function clearSuiteObjects()
262253
{
263254
$this->suiteObjects = [];
264255
}
256+
257+
/**
258+
* Resolve secret values in $overrideFields
259+
*
260+
* @param array $overrideFields
261+
* @return array
262+
*/
263+
private function resolveOverrideFields($overrideFields)
264+
{
265+
foreach ($overrideFields as $index => $field) {
266+
if (is_array($field)) {
267+
$overrideFields[$index] = $this->resolveOverrideFields($field);
268+
} elseif (is_string($field)) {
269+
try {
270+
$decrptedField = CredentialStore::getInstance()->decryptAllSecretsInString($field);
271+
if ($decrptedField !== false) {
272+
$overrideFields[$index] = $decrptedField;
273+
}
274+
} catch (TestFrameworkException $e) {
275+
//catch exception if Credentials are not defined
276+
}
277+
}
278+
}
279+
return $overrideFields;
280+
}
265281
}

src/Magento/FunctionalTestingFramework/Helper/HelperContainer.php

+18-7
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
namespace Magento\FunctionalTestingFramework\Helper;
89

@@ -11,20 +12,30 @@
1112
/**
1213
* Class HelperContainer
1314
*/
14-
class HelperContainer
15+
class HelperContainer extends \Codeception\Module
1516
{
1617
/**
1718
* @var Helper[]
1819
*/
1920
private $helpers = [];
2021

2122
/**
22-
* HelperContainer constructor.
23-
* @param array $helpers
23+
* Create custom helper class.
24+
*
25+
* @param string $helperClass
26+
* @return Helper
27+
* @throws \Exception
2428
*/
25-
public function __construct(array $helpers = [])
29+
public function create(string $helperClass): Helper
2630
{
27-
$this->helpers = $helpers;
31+
if (get_parent_class($helperClass) !== Helper::class) {
32+
throw new \Exception("Helper class must extend " . Helper::class);
33+
}
34+
if (!isset($this->helpers[$helperClass])) {
35+
$this->helpers[$helperClass] = $this->moduleContainer->create($helperClass);
36+
}
37+
38+
return $this->helpers[$helperClass];
2839
}
2940

3041
/**
@@ -34,7 +45,7 @@ public function __construct(array $helpers = [])
3445
* @return Helper
3546
* @throws TestFrameworkException
3647
*/
37-
public function get(string $className)
48+
public function get(string $className): Helper
3849
{
3950
if ($this->has($className)) {
4051
return $this->helpers[$className];
@@ -48,7 +59,7 @@ public function get(string $className)
4859
* @param string $className
4960
* @return boolean
5061
*/
51-
public function has(string $className)
62+
public function has(string $className): bool
5263
{
5364
return array_key_exists($className, $this->helpers);
5465
}

src/Magento/FunctionalTestingFramework/Helper/views/TestInjectMethod.mustache

+6-10
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,10 @@
66
/**
77
* Special method which automatically creates the respective objects.
88
*/
9-
public function _inject(
10-
{{argumentsWithTypes}}
11-
) {
12-
$this->helperContainer = new \Magento\FunctionalTestingFramework\Helper\HelperContainer(
13-
[
14-
{{#arguments}}
15-
'{{type}}' => {{var}},
16-
{{/arguments}}
17-
]
18-
);
9+
public function _inject(\Magento\FunctionalTestingFramework\Helper\HelperContainer $helperContainer)
10+
{
11+
$this->helperContainer = $helperContainer;
12+
{{#arguments}}
13+
$this->helperContainer->create("{{type}}");
14+
{{/arguments}}
1915
}

src/Magento/FunctionalTestingFramework/ObjectManager/ObjectHandlerInterface.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public static function getInstance();
2424
* Function to return a single object by name
2525
*
2626
* @param string $objectName
27-
* @return object
27+
* @return mixed
2828
*/
2929
public function getObject($objectName);
3030

src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public function execute(InputInterface $input)
6565

6666
$this->output = $this->scriptUtil->printErrorsToFile(
6767
$this->errors,
68-
self::ERROR_LOG_FILENAME,
68+
StaticChecksList::getErrorFilesPath() . DIRECTORY_SEPARATOR . self::ERROR_LOG_FILENAME . '.txt',
6969
self::ERROR_LOG_MESSAGE
7070
);
7171
}

src/Magento/FunctionalTestingFramework/StaticCheck/AnnotationsCheck.php

+11-5
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,11 @@ public function execute(InputInterface $input)
7070
$allTests = TestObjectHandler::getInstance(false)->getAllObjects();
7171

7272
foreach ($allTests as $test) {
73+
if ($this->validateSkipIssueId($test)) {
74+
//if test is skipped ignore other checks
75+
continue;
76+
}
7377
$this->validateRequiredAnnotations($test);
74-
$this->validateSkipIssueId($test);
7578
$this->aggregateStoriesTitlePairs($test);
7679
$this->aggregateTestCaseIdTitlePairs($test);
7780
}
@@ -82,7 +85,7 @@ public function execute(InputInterface $input)
8285
$scriptUtil = new ScriptUtil();
8386
$this->output = $scriptUtil->printErrorsToFile(
8487
$this->errors,
85-
self::ERROR_LOG_FILENAME,
88+
StaticChecksList::getErrorFilesPath() . DIRECTORY_SEPARATOR . self::ERROR_LOG_FILENAME . '.txt',
8689
self::ERROR_LOG_MESSAGE
8790
);
8891
}
@@ -150,19 +153,22 @@ private function validateRequiredAnnotations($test)
150153
* Validates that if the test is skipped, that it has an issueId value.
151154
*
152155
* @param TestObject $test
153-
* @return void
156+
* @return boolean
154157
*/
155158
private function validateSkipIssueId($test)
156159
{
160+
$validateSkipped = false;
157161
$annotations = $test->getAnnotations();
158162

159163
$skip = $annotations['skip'] ?? null;
160164
if ($skip !== null) {
161-
$issueId = $skip[0] ?? null;
162-
if ($issueId === null || strlen($issueId) == 0) {
165+
$validateSkipped = true;
166+
if ((!isset($skip[0]) || strlen($skip[0]) == 0)
167+
&& (!isset($skip['issueId']) || strlen($skip['issueId']) == 0)) {
163168
$this->errors[][] = "Test {$test->getName()} is skipped but the issueId is empty.";
164169
}
165170
}
171+
return $validateSkipped;
166172
}
167173

168174
/**

src/Magento/FunctionalTestingFramework/StaticCheck/DeprecatedEntityUsageCheck.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public function execute(InputInterface $input)
128128
// Hold on to the output and print any errors to a file
129129
$this->output = $this->scriptUtil->printErrorsToFile(
130130
$this->errors,
131-
self::ERROR_LOG_FILENAME,
131+
StaticChecksList::getErrorFilesPath() . DIRECTORY_SEPARATOR . self::ERROR_LOG_FILENAME . '.txt',
132132
self::ERROR_LOG_MESSAGE
133133
);
134134
}

src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php

+25
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77

88
namespace Magento\FunctionalTestingFramework\StaticCheck;
99

10+
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
11+
use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter;
12+
1013
/**
1114
* Class StaticChecksList has a list of static checks to run on test xml
1215
* @codingStandardsIgnoreFile
1316
*/
1417
class StaticChecksList implements StaticCheckListInterface
1518
{
1619
const DEPRECATED_ENTITY_USAGE_CHECK_NAME = 'deprecatedEntityUsage';
20+
const STATIC_RESULTS = 'tests' . DIRECTORY_SEPARATOR .'_output' . DIRECTORY_SEPARATOR . 'static-results';
1721

1822
/**
1923
* Property contains all static check scripts.
@@ -22,10 +26,18 @@ class StaticChecksList implements StaticCheckListInterface
2226
*/
2327
private $checks;
2428

29+
/**
30+
* Directory path for static checks error files
31+
*
32+
* @var string
33+
*/
34+
private static $errorFilesPath = null;
35+
2536
/**
2637
* Constructor
2738
*
2839
* @param array $checks
40+
* @throws TestFrameworkException
2941
*/
3042
public function __construct(array $checks = [])
3143
{
@@ -35,6 +47,11 @@ public function __construct(array $checks = [])
3547
self::DEPRECATED_ENTITY_USAGE_CHECK_NAME => new DeprecatedEntityUsageCheck(),
3648
'annotations' => new AnnotationsCheck()
3749
] + $checks;
50+
51+
// Static checks error files directory
52+
if (null === self::$errorFilesPath) {
53+
self::$errorFilesPath = FilePathFormatter::format(TESTS_BP) . self::STATIC_RESULTS;
54+
}
3855
}
3956

4057
/**
@@ -44,4 +61,12 @@ public function getStaticChecks()
4461
{
4562
return $this->checks;
4663
}
64+
65+
/**
66+
* Return the directory path for the static check error files
67+
*/
68+
public static function getErrorFilesPath()
69+
{
70+
return self::$errorFilesPath;
71+
}
4772
}

src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public function execute(InputInterface $input)
121121
// hold on to the output and print any errors to a file
122122
$this->output = $this->scriptUtil->printErrorsToFile(
123123
$this->errors,
124-
self::ERROR_LOG_FILENAME,
124+
StaticChecksList::getErrorFilesPath() . DIRECTORY_SEPARATOR . self::ERROR_LOG_FILENAME . '.txt',
125125
self::ERROR_LOG_MESSAGE
126126
);
127127
}

src/Magento/FunctionalTestingFramework/Suite/Generators/GroupClassGenerator.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,18 @@ private function buildHookMustacheArray($hookObj)
131131
{
132132
$actions = [];
133133
$mustacheHookArray['actions'][] = ['webDriverInit' => true];
134+
$mustacheHookArray['helpers'] = [];
134135

135136
foreach ($hookObj->getActions() as $action) {
136137
/** @var ActionObject $action */
137138
$index = count($actions);
139+
if ($action->getType() === ActionObject::ACTION_TYPE_HELPER) {
140+
$mustacheHookArray['helpers'][] = $action->getCustomActionAttributes()['class'];
141+
}
138142
//deleteData contains either url or createDataKey, if it contains the former it needs special formatting
139143
if ($action->getType() !== "createData"
140144
&& !array_key_exists(TestGenerator::REQUIRED_ENTITY_REFERENCE, $action->getCustomActionAttributes())) {
141-
$actions = $this->buildWebDriverActionsMustacheArray($action, $actions, $index);
145+
$actions = $this->buildWebDriverActionsMustacheArray($action, $actions);
142146
continue;
143147
}
144148

src/Magento/FunctionalTestingFramework/Suite/views/SuiteClass.mustache

+13
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,25 @@ class {{suiteName}} extends \Codeception\GroupObject
2020
private $testCount = {{testCount}};
2121
private $preconditionFailure = null;
2222
private $currentTestRun = 0;
23+
{{#helpers}}
24+
/**
25+
* @var \Magento\FunctionalTestingFramework\Helper\HelperContainer $helperContainer
26+
*/
27+
private $helperContainer;
28+
{{/helpers}}
2329
private static $HOOK_EXECUTION_INIT = "\n/******** Beginning execution of {{suiteName}} suite %s block ********/\n";
2430
private static $HOOK_EXECUTION_END = "\n/******** Execution of {{suiteName}} suite %s block complete ********/\n";
2531

2632
{{#before}}
2733
public function _before(\Codeception\Event\TestEvent $e)
2834
{
35+
{{#helpers}}
36+
/** @var \Magento\FunctionalTestingFramework\Helper\HelperContainer $helperContainer */
37+
$this->helperContainer = $this->getModule('\Magento\FunctionalTestingFramework\Helper\HelperContainer');
38+
{{/helpers}}
39+
{{#helpers}}
40+
$this->helperContainer->create("{{ . }}");
41+
{{/helpers}}
2942
// increment test count per execution
3043
$this->currentTestRun++;
3144
$this->executePreConditions();

0 commit comments

Comments
 (0)