diff --git a/dev/tests/_bootstrap.php b/dev/tests/_bootstrap.php
index 059441721..9d3750ec6 100644
--- a/dev/tests/_bootstrap.php
+++ b/dev/tests/_bootstrap.php
@@ -9,9 +9,11 @@
$vendorAutoloadPath = realpath(PROJECT_ROOT . '/vendor/autoload.php');
$mftfTestCasePath = realpath(PROJECT_ROOT . '/dev/tests/util/MftfTestCase.php');
+$mftfStaticTestCasePath = realpath(PROJECT_ROOT . '/dev/tests/util/MftfStaticTestCase.php');
require_once $vendorAutoloadPath;
require_once $mftfTestCasePath;
+require_once $mftfStaticTestCasePath;
// Set up AspectMock
$kernel = \AspectMock\Kernel::getInstance();
diff --git a/dev/tests/util/MftfStaticTestCase.php b/dev/tests/util/MftfStaticTestCase.php
new file mode 100644
index 000000000..708561031
--- /dev/null
+++ b/dev/tests/util/MftfStaticTestCase.php
@@ -0,0 +1,49 @@
+getMockBuilder(InputInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ if ($path) {
+ $input->method('getOption')
+ ->with('path')
+ ->willReturn($path);
+ }
+ return $input;
+ }
+
+ public function tearDown(): void
+ {
+ DirSetupUtil::rmdirRecursive(self::STATIC_RESULTS_DIR);
+ }
+}
diff --git a/dev/tests/verification/PauseCheckModule/ActionGroup/ActionGroupWithMultiplePausesActionGroup.xml b/dev/tests/verification/PauseCheckModule/ActionGroup/ActionGroupWithMultiplePausesActionGroup.xml
new file mode 100644
index 000000000..5e9299631
--- /dev/null
+++ b/dev/tests/verification/PauseCheckModule/ActionGroup/ActionGroupWithMultiplePausesActionGroup.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/verification/PauseCheckModule/ActionGroup/ActionGroupWithNoPauseActionGroup.xml b/dev/tests/verification/PauseCheckModule/ActionGroup/ActionGroupWithNoPauseActionGroup.xml
new file mode 100644
index 000000000..8acae47e8
--- /dev/null
+++ b/dev/tests/verification/PauseCheckModule/ActionGroup/ActionGroupWithNoPauseActionGroup.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/verification/PauseCheckModule/ActionGroup/ActionGroupWithPauseActionGroup.xml b/dev/tests/verification/PauseCheckModule/ActionGroup/ActionGroupWithPauseActionGroup.xml
new file mode 100644
index 000000000..aaef1befa
--- /dev/null
+++ b/dev/tests/verification/PauseCheckModule/ActionGroup/ActionGroupWithPauseActionGroup.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/verification/PauseCheckModule/Suite/suiteWithMultiplePauseActionsSuite.xml b/dev/tests/verification/PauseCheckModule/Suite/suiteWithMultiplePauseActionsSuite.xml
new file mode 100644
index 000000000..47ff1088b
--- /dev/null
+++ b/dev/tests/verification/PauseCheckModule/Suite/suiteWithMultiplePauseActionsSuite.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+ dataHere
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/verification/PauseCheckModule/Suite/suiteWithPauseActionSuite.xml b/dev/tests/verification/PauseCheckModule/Suite/suiteWithPauseActionSuite.xml
new file mode 100644
index 000000000..71a3b5769
--- /dev/null
+++ b/dev/tests/verification/PauseCheckModule/Suite/suiteWithPauseActionSuite.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+ dataHere
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/verification/PauseCheckModule/Test/TestWithMultiplePauseActionsTest.xml b/dev/tests/verification/PauseCheckModule/Test/TestWithMultiplePauseActionsTest.xml
new file mode 100644
index 000000000..fa47e976c
--- /dev/null
+++ b/dev/tests/verification/PauseCheckModule/Test/TestWithMultiplePauseActionsTest.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/verification/PauseCheckModule/Test/TestWithPauseActionTest.xml b/dev/tests/verification/PauseCheckModule/Test/TestWithPauseActionTest.xml
new file mode 100644
index 000000000..70d0903b8
--- /dev/null
+++ b/dev/tests/verification/PauseCheckModule/Test/TestWithPauseActionTest.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/verification/Resources/StaticChecks/mftf-pause-action-usage-checks.txt b/dev/tests/verification/Resources/StaticChecks/mftf-pause-action-usage-checks.txt
new file mode 100644
index 000000000..fd042a24c
--- /dev/null
+++ b/dev/tests/verification/Resources/StaticChecks/mftf-pause-action-usage-checks.txt
@@ -0,0 +1,30 @@
+
+File "/verification/PauseCheckModule/ActionGroup/ActionGroupWithMultiplePausesActionGroup.xml"
+contains pause action(s):
+
+ ActionGroupWithMultiplePausesActionGroup has pause action at stepKey(s): pauseAfterFillField1, pauseAfterFillField2, pauseAfterFillField3
+
+File "/verification/PauseCheckModule/ActionGroup/ActionGroupWithPauseActionGroup.xml"
+contains pause action(s):
+
+ ActionGroupWithPauseActionGroup has pause action at stepKey(s): pauseAfterFillField2
+
+File "/verification/PauseCheckModule/Test/TestWithMultiplePauseActionsTest.xml"
+contains pause action(s):
+
+ TestWithMultiplePauseActionsTest has pause action at stepKey(s): pauseBeforeAmOnPageKey, pauseAfterStep2, pauseAfterAmOnPageKey
+
+File "/verification/PauseCheckModule/Test/TestWithPauseActionTest.xml"
+contains pause action(s):
+
+ TestWithPauseActionTest has pause action at stepKey(s): pauseAfterStep3
+
+File "/verification/PauseCheckModule/Suite/suiteWithMultiplePauseActionsSuite.xml"
+contains pause action(s):
+
+ suiteWithMultiplePauseActionsSuite has pause action at stepKey(s): pauseCreate1, pauseFillAfter
+
+File "/verification/PauseCheckModule/Suite/suiteWithPauseActionSuite.xml"
+contains pause action(s):
+
+ suiteWithPauseActionSuite has pause action at stepKey(s): pauseSuite
diff --git a/dev/tests/verification/Tests/StaticCheck/DeprecationStaticCheckTest.php b/dev/tests/verification/Tests/StaticCheck/DeprecationStaticCheckTest.php
index bafe586ac..f6aef65f6 100644
--- a/dev/tests/verification/Tests/StaticCheck/DeprecationStaticCheckTest.php
+++ b/dev/tests/verification/Tests/StaticCheck/DeprecationStaticCheckTest.php
@@ -8,18 +8,11 @@
use AspectMock\Test as AspectMock;
use Magento\FunctionalTestingFramework\StaticCheck\DeprecatedEntityUsageCheck;
use Magento\FunctionalTestingFramework\StaticCheck\StaticChecksList;
-use Magento\FunctionalTestingFramework\Util\Filesystem\DirSetupUtil;
-use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Input\InputInterface;
+use tests\util\MftfStaticTestCase;
-class DeprecationStaticCheckTest extends TestCase
+class DeprecationStaticCheckTest extends MftfStaticTestCase
{
- const STATIC_RESULTS_DIR = TESTS_MODULE_PATH .
- DIRECTORY_SEPARATOR .
- '_output' .
- DIRECTORY_SEPARATOR .
- 'static-results';
-
const LOG_FILE = self::STATIC_RESULTS_DIR .
DIRECTORY_SEPARATOR .
DeprecatedEntityUsageCheck::ERROR_LOG_FILENAME .
@@ -30,20 +23,6 @@ class DeprecationStaticCheckTest extends TestCase
'DeprecationCheckModule'.
DIRECTORY_SEPARATOR;
- const RESOURCES_PATH = TESTS_MODULE_PATH .
- DIRECTORY_SEPARATOR .
- "Resources" .
- DIRECTORY_SEPARATOR .
- 'StaticChecks';
-
- public static function setUpBeforeClass(): void
- {
- // remove static-results if it exists
- if (file_exists(self::STATIC_RESULTS_DIR)) {
- DirSetupUtil::rmdirRecursive(self::STATIC_RESULTS_DIR);
- }
- }
-
/**
* test static-check DeprecatedEntityUsageCheck.
*
@@ -68,25 +47,4 @@ public function testDeprecatedEntityUsageCheck()
self::LOG_FILE
);
}
-
- /**
- * Sets input interface
- * @param $path
- * @return \PHPUnit\Framework\MockObject\MockObject
- */
- public function mockInputInterface($path)
- {
- $input = $this->getMockBuilder(InputInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $input->method('getOption')
- ->with('path')
- ->willReturn($path);
- return $input;
- }
-
- public function tearDown(): void
- {
- DirSetupUtil::rmdirRecursive(self::STATIC_RESULTS_DIR);
- }
}
diff --git a/dev/tests/verification/Tests/StaticCheck/PauseActionStaticCheckTest.php b/dev/tests/verification/Tests/StaticCheck/PauseActionStaticCheckTest.php
new file mode 100644
index 000000000..7c8f77c2f
--- /dev/null
+++ b/dev/tests/verification/Tests/StaticCheck/PauseActionStaticCheckTest.php
@@ -0,0 +1,51 @@
+mockInputInterface(self::TEST_MODULE_PATH);
+ AspectMock::double(StaticChecksList::class, ['getErrorFilesPath' => self::STATIC_RESULTS_DIR]);
+
+ /** @var InputInterface $input */
+ $staticCheck->execute($input);
+
+ $this->assertTrue(file_exists(self::LOG_FILE));
+ $this->assertFileEquals(
+ self::RESOURCES_PATH.
+ DIRECTORY_SEPARATOR .
+ PauseActionUsageCheck::ERROR_LOG_FILENAME .
+ ".txt",
+ self::LOG_FILE
+ );
+ }
+}
diff --git a/docs/commands/mftf.md b/docs/commands/mftf.md
index 3c170e5ca..0c5c86285 100644
--- a/docs/commands/mftf.md
+++ b/docs/commands/mftf.md
@@ -449,7 +449,7 @@ vendor/bin/mftf static-checks []...
| Option | Description |
|-----------------------|-----------------------------------------------------------------------------------------------------------|
-| `-p, --path` | Path to a MFTF test module to run "deprecatedEntityUsage" static check script. Option is ignored by other static check scripts.
+| `-p, --path` | Path to a MFTF test module to run "deprecatedEntityUsage" and "pauseActionUsage" static check scripts. Option is ignored by other static check scripts.
#### Examples
@@ -479,6 +479,10 @@ vendor/bin/mftf static-checks actionGroupArguments
vendor/bin/mftf static-checks deprecatedEntityUsage
```
+```bash
+vendor/bin/mftf static-checks pauseActionUsage
+```
+
```bash
vendor/bin/mftf static-checks annotations
```
@@ -487,6 +491,10 @@ vendor/bin/mftf static-checks annotations
vendor/bin/mftf static-checks deprecatedEntityUsage -p path/to/mftf/test/module
```
+```bash
+vendor/bin/mftf static-checks pauseActionUsage -p path/to/mftf/test/module
+```
+
```bash
vendor/bin/mftf static-checks testDependencies actionGroupArguments
```
@@ -499,6 +507,7 @@ vendor/bin/mftf static-checks testDependencies actionGroupArguments
|`actionGroupArguments` | Checks that action groups do not have unused arguments.|
|`deprecatedEntityUsage`| Checks that deprecated test entities are not being referenced.|
|`annotations`| Checks various details of test annotations, such as missing annotations or duplicate annotations.|
+|`pauseUsage`| Checks that pause action is not used in action groups, tests or suites.|
#### Defining ruleset
diff --git a/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php b/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php
index fe07dbaaf..806508ef8 100644
--- a/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php
+++ b/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php
@@ -151,12 +151,17 @@ private function validateInput(InputInterface $input)
}
if ($input->getOption('path')) {
- if ( (count($this->staticCheckObjects) !== 1)
- || array_keys($this->staticCheckObjects)[0] !== StaticChecksList::DEPRECATED_ENTITY_USAGE_CHECK_NAME )
+ if ((count($this->staticCheckObjects) !== 1)
+ || !in_array(
+ array_keys($this->staticCheckObjects)[0],
+ [
+ StaticChecksList::DEPRECATED_ENTITY_USAGE_CHECK_NAME,
+ StaticChecksList::PAUSE_ACTION_USAGE_CHECK_NAME
+ ]
+ )
+ )
throw new InvalidArgumentException(
- '--path option can only be used for "'
- . StaticChecksList::DEPRECATED_ENTITY_USAGE_CHECK_NAME
- . '".'
+ '--path option is not supported for the command."'
);
}
}
diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/PauseActionUsageCheck.php b/src/Magento/FunctionalTestingFramework/StaticCheck/PauseActionUsageCheck.php
new file mode 100644
index 000000000..e7d106bf0
--- /dev/null
+++ b/src/Magento/FunctionalTestingFramework/StaticCheck/PauseActionUsageCheck.php
@@ -0,0 +1,229 @@
+scriptUtil = new ScriptUtil();
+ $modulePaths = [];
+ $includeRootPath = true;
+ $path = $input->getOption('path');
+ if ($path) {
+ if (!realpath($path)) {
+ throw new \InvalidArgumentException('Invalid --path option: ' . $path);
+ }
+ $modulePaths[] = realpath($path);
+ $includeRootPath = false;
+ } else {
+ $modulePaths = $this->scriptUtil->getAllModulePaths();
+ }
+
+ $this->testXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, 'Test');
+ $this->actionGroupXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, 'ActionGroup');
+ $this->suiteXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, 'Suite');
+ if ($includeRootPath) {
+ $this->rootSuiteXmlFiles = $this->scriptUtil->getRootSuiteXmlFiles();
+ }
+ $this->errors = [];
+ $this->errors += $this->validatePauseActionUsageInActionGroups($this->actionGroupXmlFiles);
+ $this->errors += $this->validatePauseActionUsageInTests($this->testXmlFiles);
+ $this->errors += $this->validatePauseActionUsageInSuites($this->suiteXmlFiles);
+ $this->errors += $this->validatePauseActionUsageInSuites($this->rootSuiteXmlFiles);
+
+ $this->output = $this->scriptUtil->printErrorsToFile(
+ $this->errors,
+ StaticChecksList::getErrorFilesPath() . DIRECTORY_SEPARATOR . self::ERROR_LOG_FILENAME . '.txt',
+ self::ERROR_LOG_MESSAGE
+ );
+ }
+
+ /**
+ * Finds usages of pause action in action group files
+ * @param array $actionGroupXmlFiles
+ * @return array
+ */
+ private function validatePauseActionUsageInActionGroups($actionGroupXmlFiles)
+ {
+ $actionGroupErrors = [];
+ foreach ($actionGroupXmlFiles as $filePath) {
+ $domDocument = new \DOMDocument();
+ $domDocument->load($filePath);
+ $actionGroup = $domDocument->getElementsByTagName('actionGroup')->item(0);
+ $violatingStepKeys = $this->findViolatingPauseStepKeys($actionGroup);
+ $actionGroupErrors = array_merge($actionGroupErrors, $this->setErrorOutput($violatingStepKeys, $filePath));
+ }
+ return $actionGroupErrors;
+ }
+
+ /**
+ * Finds usages of pause action in test files
+ * @param array $testXmlFiles
+ * @return array
+ */
+ private function validatePauseActionUsageInTests($testXmlFiles)
+ {
+ $testErrors = [];
+ foreach ($testXmlFiles as $filePath) {
+ $domDocument = new \DOMDocument();
+ $domDocument->load($filePath);
+ $test = $domDocument->getElementsByTagName('test')->item(0);
+ $violatingStepKeys = $this->findViolatingPauseStepKeys($test);
+ $testErrors = array_merge($testErrors, $this->setErrorOutput($violatingStepKeys, $filePath));
+ }
+ return $testErrors;
+ }
+
+ /**
+ * Finds usages of pause action in suite files
+ * @param array $suiteXmlFiles
+ * @return array
+ */
+ private function validatePauseActionUsageInSuites($suiteXmlFiles)
+ {
+ $suiteErrors = [];
+ foreach ($suiteXmlFiles as $filePath) {
+ $domDocument = new \DOMDocument();
+ $domDocument->load($filePath);
+ $suite = $domDocument->getElementsByTagName('suite')->item(0);
+ $violatingStepKeys = $this->findViolatingPauseStepKeys($suite);
+ $suiteErrors = array_merge($suiteErrors, $this->setErrorOutput($violatingStepKeys, $filePath));
+ }
+ return $suiteErrors;
+ }
+
+ /**
+ * Finds violating pause action step keys
+ * @param \DomNode $entity
+ * @return array
+ */
+ private function findViolatingPauseStepKeys($entity)
+ {
+ $violatingStepKeys = [];
+ $entityName = $entity->getAttribute('name');
+ $references = $entity->getElementsByTagName('pause');
+
+ foreach ($references as $reference) {
+ $pauseStepKey = $reference->getAttribute('stepKey');
+ $violatingStepKeys[$entityName][] = $pauseStepKey;
+ }
+ return $violatingStepKeys;
+ }
+
+ /**
+ * Return array containing all errors found after running the execute() function.
+ * @return array
+ */
+ public function getErrors()
+ {
+ return $this->errors;
+ }
+
+ /**
+ * Return string of a short human readable result of the check. For example: "No errors found."
+ * @return string
+ */
+ public function getOutput()
+ {
+ return $this->output;
+ }
+
+ /**
+ * Build and return error output for pause action usages
+ *
+ * @param array $violatingReferences
+ * @param SplFileInfo $path
+ * @return mixed
+ */
+ private function setErrorOutput($violatingReferences, $path)
+ {
+ $testErrors = [];
+
+ $filePath = StaticChecksList::getFilePath($path->getRealPath());
+
+ if (!empty($violatingReferences)) {
+ // Build error output
+ $errorOutput = "\nFile \"{$filePath}\"";
+ $errorOutput .= "\ncontains pause action(s):\n\t\t";
+ foreach ($violatingReferences as $entityName => $stepKey) {
+ $errorOutput .= "\n\t {$entityName} has pause action at stepKey(s): " . implode(", ", $stepKey);
+ }
+ $testErrors[$filePath][] = $errorOutput;
+ }
+ return $testErrors;
+ }
+}
diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php
index ba2139276..07c52ce8c 100644
--- a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php
+++ b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php
@@ -17,6 +17,7 @@
class StaticChecksList implements StaticCheckListInterface
{
const DEPRECATED_ENTITY_USAGE_CHECK_NAME = 'deprecatedEntityUsage';
+ const PAUSE_ACTION_USAGE_CHECK_NAME = 'pauseActionUsage';
const STATIC_RESULTS = 'tests' . DIRECTORY_SEPARATOR .'_output' . DIRECTORY_SEPARATOR . 'static-results';
/**
@@ -45,7 +46,8 @@ public function __construct(array $checks = [])
'testDependencies' => new TestDependencyCheck(),
'actionGroupArguments' => new ActionGroupArgumentsCheck(),
self::DEPRECATED_ENTITY_USAGE_CHECK_NAME => new DeprecatedEntityUsageCheck(),
- 'annotations' => new AnnotationsCheck()
+ 'annotations' => new AnnotationsCheck(),
+ self::PAUSE_ACTION_USAGE_CHECK_NAME => new PauseActionUsageCheck()
] + $checks;
// Static checks error files directory
diff --git a/src/Magento/FunctionalTestingFramework/Util/Script/ScriptUtil.php b/src/Magento/FunctionalTestingFramework/Util/Script/ScriptUtil.php
index 14f9c27e0..11afa5cc1 100644
--- a/src/Magento/FunctionalTestingFramework/Util/Script/ScriptUtil.php
+++ b/src/Magento/FunctionalTestingFramework/Util/Script/ScriptUtil.php
@@ -101,7 +101,7 @@ public function getModuleXmlFilesByScope($modulePaths, $scope)
if (!realpath($modulePath . $scopePath)) {
continue;
}
- $finder->files()->followLinks()->in($modulePath . $scopePath)->name("*.xml");
+ $finder->files()->followLinks()->in($modulePath . $scopePath)->name("*.xml")->sortByName();
$found = true;
}
return $found ? $finder->files() : [];