Skip to content

Commit

Permalink
Merge pull request #394 from magento-commerce/MFTF4.7.2-Release
Browse files Browse the repository at this point in the history
MFTF4.7.2 : Release
  • Loading branch information
KevinBKozan authored Apr 2, 2024
2 parents 036c0db + 0fdedc8 commit 352d35f
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 6 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Magento Functional Testing Framework Changelog
================================================

4.7.2
---------
### Enhancements
* Fail static test when introduced filename does not equal the MFTF object name
contained within.

4.7.1
---------
### Enhancements
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "magento/magento2-functional-testing-framework",
"description": "Magento2 Functional Testing Framework",
"type": "library",
"version": "4.7.1",
"version": "4.7.2",
"license": "AGPL-3.0",
"keywords": ["magento", "automation", "functional", "testing"],
"config": {
Expand Down
2 changes: 1 addition & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace tests\unit\Magento\FunctionalTestFramework\Util;

use tests\unit\Util\MagentoTestCase;
use Magento\FunctionalTestingFramework\StaticCheck\ClassFileNamingCheck;
use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil;

class ClassFileNameCheckTest extends MagentoTestCase
{
/**
* This Test checks if the file name is renamed to match the class name if mismatch found in class and file name
*/
public function testClassAndFileMismatchStaticCheckWhenViolationsFound()
{
$scriptUtil = new ScriptUtil();
$modulePaths = $scriptUtil->getAllModulePaths();
$testXmlFiles = $scriptUtil->getModuleXmlFilesByScope($modulePaths, "Test");
$classFileNameCheck = new ClassFileNamingCheck();
$result = $classFileNameCheck->findErrorsInFileSet($testXmlFiles, "test");
$this->assertMatchesRegularExpression('/does not match with file name/', $result[array_keys($result)[0]][0]);
}

/**
* This Test checks if the file name is renamed to match the class name if
* mismatch not found in class and file name
*/
public function testClassAndFileMismatchStaticCheckWhenViolationsNotFound()
{
$scriptUtil = new ScriptUtil();
$modulePaths = $scriptUtil->getAllModulePaths();
$testXmlFiles = $scriptUtil->getModuleXmlFilesByScope($modulePaths, "Page");
$classFileNameCheck = new ClassFileNamingCheck();
$result = $classFileNameCheck->findErrorsInFileSet($testXmlFiles, "page");
$this->assertEquals(count($result), 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ protected function execute(InputInterface $input, OutputInterface $output)

$staticOutput = $staticCheck->getOutput();
LoggingUtil::getInstance()->getLogger(get_class($staticCheck))->info($staticOutput);
$this->ioStyle->text($staticOutput);
$this->ioStyle->text($staticOutput??"");

$this->ioStyle->text('Total execution time is ' . (string)($end - $start) . ' seconds.' . PHP_EOL);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\FunctionalTestingFramework\StaticCheck;

use Symfony\Component\Console\Input\InputInterface;
use Exception;
use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil;
use Symfony\Component\Finder\SplFileInfo;

/**
* Class ClassFileNamingCheck
* @package Magento\FunctionalTestingFramework\StaticCheck
*/
class ClassFileNamingCheck implements StaticCheckInterface
{
const ERROR_LOG_FILENAME = 'mftf-class-file-naming-check';
const ERROR_LOG_MESSAGE = 'MFTF Class File Naming Check';
const ALLOW_LIST_FILENAME = 'class-file-naming-allowlist';
const WARNING_LOG_FILENAME = 'mftf-class-file-naming-warnings';

/**
* Array containing all warnings found after running the execute() function.
* @var array
*/
private $warnings = [];
/**
* Array containing all errors found after running the execute() function.
* @var array
*/
private $errors = [];

/**
* String representing the output summary found after running the execute() function.
* @var string
*/
private $output;

/**
* @var array $allowFailureEntities
*/
private $allowFailureEntities = [];

/**
* ScriptUtil instance
*
* @var ScriptUtil
*/
private $scriptUtil;
/**
* Checks usage of pause action in action groups, tests and suites and prints out error to file.
*
* @param InputInterface $input
* @return void
* @throws Exception
*/
public function execute(InputInterface $input)
{
$this->scriptUtil = new ScriptUtil();
$modulePaths = [];
$path = $input->getOption('path');
if ($path) {
if (!realpath($path)) {
throw new \InvalidArgumentException('Invalid --path option: ' . $path);
}
$modulePaths[] = realpath($path);
} else {
$modulePaths = $this->scriptUtil->getAllModulePaths();
}
foreach ($modulePaths as $modulePath) {
if (file_exists($modulePath . DIRECTORY_SEPARATOR . self::ALLOW_LIST_FILENAME)) {
$contents = file_get_contents($modulePath . DIRECTORY_SEPARATOR . self::ALLOW_LIST_FILENAME);
foreach (explode("\n", $contents) as $entity) {
$this->allowFailureEntities[$entity] = true;
}
}
}
$testXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, "Test");
$actionGroupXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, "ActionGroup");
$pageXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, "Page");
$sectionXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, "Section");
$suiteXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, 'Suite');
$this->errors = [];
$this->errors += $this->findErrorsInFileSet($testXmlFiles, 'test');
$this->errors += $this->findErrorsInFileSet($actionGroupXmlFiles, 'actionGroup');
$this->errors += $this->findErrorsInFileSet($pageXmlFiles, 'page');
$this->errors += $this->findErrorsInFileSet($sectionXmlFiles, 'section');
$this->errors += $this->findErrorsInFileSet($suiteXmlFiles, 'suite');

// hold on to the output and print any errors to a file
$this->output = $this->scriptUtil->printErrorsToFile(
$this->errors,
StaticChecksList::getErrorFilesPath() . DIRECTORY_SEPARATOR . self::ERROR_LOG_FILENAME . '.txt',
self::ERROR_LOG_MESSAGE
);
if (!empty($this->warnings)) {
$this->output .= "\n " . $this->scriptUtil->printWarningsToFile(
$this->warnings,
StaticChecksList::getErrorFilesPath() . DIRECTORY_SEPARATOR . self::WARNING_LOG_FILENAME . '.txt',
self::ERROR_LOG_MESSAGE
);
}
}

/**
* 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;
}

/**
* Returns Violations if found
* @param SplFileInfo $files
* @param string $fileType
* @return array
*/
public function findErrorsInFileSet($files, $fileType)
{
$errors = [];
/** @var SplFileInfo $filePath */

foreach ($files as $filePath) {
$fileNameWithoutExtension = pathinfo($filePath->getFilename(), PATHINFO_FILENAME);
$domDocument = new \DOMDocument();
$domDocument->load($filePath);
$testResult = $this->getAttributesFromDOMNodeList(
$domDocument->getElementsByTagName($fileType),
["type" => 'name']
);
if ($fileNameWithoutExtension != array_values($testResult[0])[0]) {
$isInAllowList = array_key_exists(array_values($testResult[0])[0], $this->allowFailureEntities);
if ($isInAllowList) {
$errorOutput = ucfirst($fileType). " name does not match with file name
{$filePath->getRealPath()}. ".ucfirst($fileType)." ".array_values($testResult[0])[0];
$this->warnings[$filePath->getFilename()][] = $errorOutput;
continue;
}
$errorOutput = ucfirst($fileType). " name does not match with file name
{$filePath->getRealPath()}. ".ucfirst($fileType)." ".array_values($testResult[0])[0];
$errors[$filePath->getFilename()][] = $errorOutput;
}
}
return $errors;
}

/**
* Return attribute value for each node in DOMNodeList as an array
*
* @param DOMNodeList $nodes
* @param string $attributeName
* @return array
*/
public function getAttributesFromDOMNodeList($nodes, $attributeName)
{
$attributes = [];
foreach ($nodes as $node) {
if (is_string($attributeName)) {
$attributeValue = $node->getAttribute($attributeName);
} else {
$attributeValue = [$node->getAttribute(key($attributeName)) =>
$node->getAttribute($attributeName[key($attributeName)])];
}
if (!empty($attributeValue)) {
$attributes[] = $attributeValue;
}
}
return $attributes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class StaticChecksList implements StaticCheckListInterface
const PAUSE_ACTION_USAGE_CHECK_NAME = 'pauseActionUsage';
const CREATED_DATA_FROM_OUTSIDE_ACTIONGROUP = 'createdDataFromOutsideActionGroup';
const UNUSED_ENTITY_CHECK = 'unusedEntityCheck';

const CLASS_FILE_NAMING_CHECK = 'classFileNamingCheck';

const STATIC_RESULTS = 'tests' . DIRECTORY_SEPARATOR .'_output' . DIRECTORY_SEPARATOR . 'static-results';

/**
Expand Down Expand Up @@ -51,8 +54,10 @@ public function __construct(array $checks = [])
'annotations' => new AnnotationsCheck(),
self::PAUSE_ACTION_USAGE_CHECK_NAME => new PauseActionUsageCheck(),
self::UNUSED_ENTITY_CHECK => new UnusedEntityCheck(),
self::CREATED_DATA_FROM_OUTSIDE_ACTIONGROUP => new CreatedDataFromOutsideActionGroupCheck(),
] + $checks;
self::CREATED_DATA_FROM_OUTSIDE_ACTIONGROUP => new CreatedDataFromOutsideActionGroupCheck(),
self::CLASS_FILE_NAMING_CHECK => new ClassFileNamingCheck(),

] + $checks;

// Static checks error files directory
if (null === self::$errorFilesPath) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public function getErrors(): array
*/
public function getOutput(): string
{
return $this->output;
return $this->output??"";
}

/**
Expand Down

0 comments on commit 352d35f

Please sign in to comment.