diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Page/MFTFDocPage.xml b/dev/tests/functional/tests/MFTF/DevDocsTest/Page/MFTFDocPage.xml
similarity index 100%
rename from dev/tests/functional/tests/MFTF/DevDocs/Page/MFTFDocPage.xml
rename to dev/tests/functional/tests/MFTF/DevDocsTest/Page/MFTFDocPage.xml
diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Section/ContentSection.xml b/dev/tests/functional/tests/MFTF/DevDocsTest/Section/ContentSection.xml
similarity index 100%
rename from dev/tests/functional/tests/MFTF/DevDocs/Section/ContentSection.xml
rename to dev/tests/functional/tests/MFTF/DevDocsTest/Section/ContentSection.xml
diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml b/dev/tests/functional/tests/MFTF/DevDocsTest/Test/DevDocsTest.xml
similarity index 100%
rename from dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml
rename to dev/tests/functional/tests/MFTF/DevDocsTest/Test/DevDocsTest.xml
diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Suite/Handlers/SuiteObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Suite/Handlers/SuiteObjectHandlerTest.php
index 99125a9e3..5bf29507c 100644
--- a/dev/tests/unit/Magento/FunctionalTestFramework/Suite/Handlers/SuiteObjectHandlerTest.php
+++ b/dev/tests/unit/Magento/FunctionalTestFramework/Suite/Handlers/SuiteObjectHandlerTest.php
@@ -15,9 +15,16 @@
use Magento\FunctionalTestingFramework\Util\MagentoTestCase;
use tests\unit\Util\SuiteDataArrayBuilder;
use tests\unit\Util\TestDataArrayBuilder;
+use tests\unit\Util\MockModuleResolverBuilder;
class SuiteObjectHandlerTest extends MagentoTestCase
{
+ public function setUp()
+ {
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup();
+ }
+
/**
* Tests basic parsing and accesors of suite object and suite object supporting classes
*/
diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php
index eb6298afc..29158b0f5 100644
--- a/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php
+++ b/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php
@@ -20,10 +20,10 @@
use tests\unit\Util\SuiteDataArrayBuilder;
use tests\unit\Util\TestDataArrayBuilder;
use tests\unit\Util\TestLoggingUtil;
+use tests\unit\Util\MockModuleResolverBuilder;
class SuiteGeneratorTest extends MagentoTestCase
{
-
/**
* Setup entry append and clear for Suite Generator
*/
@@ -42,6 +42,8 @@ public static function setUpBeforeClass()
public function setUp()
{
TestLoggingUtil::getInstance()->setMockLoggingUtil();
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup();
}
/**
diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php
index 1dbeb50db..08571b507 100644
--- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php
+++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php
@@ -8,7 +8,6 @@
use AspectMock\Test as AspectMock;
-use Go\Aop\Aspect;
use Magento\FunctionalTestingFramework\ObjectManager;
use Magento\FunctionalTestingFramework\ObjectManagerFactory;
use Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler;
@@ -16,10 +15,10 @@
use Magento\FunctionalTestingFramework\Test\Objects\TestHookObject;
use Magento\FunctionalTestingFramework\Test\Objects\TestObject;
use Magento\FunctionalTestingFramework\Test\Parsers\TestDataParser;
-use Magento\FunctionalTestingFramework\Test\Util\ActionObjectExtractor;
use Magento\FunctionalTestingFramework\Test\Util\TestObjectExtractor;
use Magento\FunctionalTestingFramework\Util\MagentoTestCase;
use tests\unit\Util\TestDataArrayBuilder;
+use tests\unit\Util\MockModuleResolverBuilder;
class TestObjectHandlerTest extends MagentoTestCase
{
@@ -40,10 +39,13 @@ public function testGetTestObject()
->withTestActions()
->build();
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup();
$this->setMockParserOutput(['tests' => $mockData]);
// run object handler method
$toh = TestObjectHandler::getInstance();
+ $mockConfig = AspectMock::double(TestObjectHandler::class, ['initTestData' => false]);
$actualTestObject = $toh->getObject($testDataArrayBuilder->testName);
// perform asserts
@@ -130,6 +132,8 @@ public function testGetTestsByGroup()
->withTestActions()
->build();
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup();
$this->setMockParserOutput(['tests' => array_merge($includeTest, $excludeTest)]);
// execute test method
@@ -150,16 +154,20 @@ public function testGetTestsByGroup()
public function testGetTestWithModuleName()
{
// set up Test Data
- $moduleExpected = "SomeTestModule";
+ $moduleExpected = "SomeModuleName";
+ $moduleExpectedTest = $moduleExpected . "Test";
$filepath = DIRECTORY_SEPARATOR .
- "user" .
+ "user" . DIRECTORY_SEPARATOR .
"magento2ce" . DIRECTORY_SEPARATOR .
"dev" . DIRECTORY_SEPARATOR .
"tests" . DIRECTORY_SEPARATOR .
"acceptance" . DIRECTORY_SEPARATOR .
"tests" . DIRECTORY_SEPARATOR .
- $moduleExpected . DIRECTORY_SEPARATOR .
- "Tests" . DIRECTORY_SEPARATOR .
+ "functional" . DIRECTORY_SEPARATOR .
+ "Vendor" . DIRECTORY_SEPARATOR .
+ $moduleExpectedTest;
+ $file = $filepath . DIRECTORY_SEPARATOR .
+ "Test" . DIRECTORY_SEPARATOR .
"text.xml";
// set up mock data
$testDataArrayBuilder = new TestDataArrayBuilder();
@@ -169,8 +177,12 @@ public function testGetTestWithModuleName()
->withAfterHook()
->withBeforeHook()
->withTestActions()
- ->withFileName($filepath)
+ ->withFileName($file)
->build();
+
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup(['Vendor_' . $moduleExpected => [$filepath]]);
+
$this->setMockParserOutput(['tests' => $mockData]);
// Execute Test Method
$toh = TestObjectHandler::getInstance();
@@ -198,4 +210,14 @@ private function setMockParserOutput($data)
->make(); // bypass the private constructor
AspectMock::double(ObjectManagerFactory::class, ['getObjectManager' => $instance]);
}
+
+ /**
+ * After method functionality
+ *
+ * @return void
+ */
+ public function tearDown()
+ {
+ AspectMock::clean();
+ }
}
diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ObjectExtensionUtilTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ObjectExtensionUtilTest.php
index b023b16c7..3b43ba00f 100644
--- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ObjectExtensionUtilTest.php
+++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ObjectExtensionUtilTest.php
@@ -20,6 +20,7 @@
use PHPUnit\Framework\TestCase;
use tests\unit\Util\TestDataArrayBuilder;
use tests\unit\Util\TestLoggingUtil;
+use tests\unit\Util\MockModuleResolverBuilder;
class ObjectExtensionUtilTest extends TestCase
{
@@ -30,6 +31,8 @@ class ObjectExtensionUtilTest extends TestCase
public function setUp()
{
TestLoggingUtil::getInstance()->setMockLoggingUtil();
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup();
}
/**
diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModulePathExtractorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModulePathExtractorTest.php
index 5efa6384b..4fb18d383 100644
--- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModulePathExtractorTest.php
+++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModulePathExtractorTest.php
@@ -7,103 +7,128 @@
namespace tests\unit\Magento\FunctionalTestFramework\Test\Util;
use Magento\FunctionalTestingFramework\Util\ModulePathExtractor;
-use PHPUnit\Framework\TestCase;
+use Magento\FunctionalTestingFramework\Util\MagentoTestCase;
+use tests\unit\Util\MockModuleResolverBuilder;
-class ModulePathExtractorTest extends TestCase
+class ModulePathExtractorTest extends MagentoTestCase
{
- const EXTENSION_PATH = "app"
- . DIRECTORY_SEPARATOR
- . "code"
- . DIRECTORY_SEPARATOR
- . "TestExtension"
- . DIRECTORY_SEPARATOR
- . "[Analytics]"
- . DIRECTORY_SEPARATOR
- . "Test"
- . DIRECTORY_SEPARATOR
- . "Mftf"
- . DIRECTORY_SEPARATOR
- . "Test"
- . DIRECTORY_SEPARATOR
- . "SomeText.xml";
-
- const MAGENTO_PATH = "dev"
- . DIRECTORY_SEPARATOR
- . "tests"
- . DIRECTORY_SEPARATOR
- . "acceptance"
- . DIRECTORY_SEPARATOR
- . "tests"
- . DIRECTORY_SEPARATOR
- . "functional"
- . DIRECTORY_SEPARATOR
- . "Magento"
- . DIRECTORY_SEPARATOR
- . "FunctionalTest"
- . DIRECTORY_SEPARATOR
- . "[Analytics]"
- . DIRECTORY_SEPARATOR
- . "Test"
- . DIRECTORY_SEPARATOR
- . "SomeText.xml";
+ /**
+ * Mock test module paths
+ *
+ * @var array
+ */
+ private $mockTestModulePaths = [
+ 'Magento_ModuleA' => ['/base/path/app/code/Magento/ModuleA/Test/Mftf'],
+ 'VendorB_ModuleB' => ['/base/path/app/code/VendorB/ModuleB/Test/Mftf'],
+ 'Magento_ModuleC' => ['/base/path/dev/tests/acceptance/tests/functional/Magento/ModuleCTest'],
+ 'VendorD_ModuleD' => ['/base/path/dev/tests/acceptance/tests/functional/VendorD/ModuleDTest'],
+ 'SomeModuleE' => ['/base/path/dev/tests/acceptance/tests/functional/FunctionalTest/SomeModuleE'],
+ 'Magento_ModuleF' => ['/base/path/vendor/magento/module-modulef/Test/Mftf'],
+ 'VendorG_ModuleG' => ['/base/path/vendor/vendorg/module-moduleg-test'],
+ ];
+
+ /**
+ * Validate module for app/code path
+ *
+ * @throws \Exception
+ */
+ public function testGetModuleAppCode()
+ {
+ $mockPath = '/base/path/app/code/Magento/ModuleA/Test/Mftf/Test/SomeTest.xml';
+
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup($this->mockTestModulePaths);
+ $extractor = new ModulePathExtractor();
+ $this->assertEquals('ModuleA', $extractor->extractModuleName($mockPath));
+ }
/**
- * Validate correct module is returned for dev/tests path
+ * Validate vendor for app/code path
+ *
* @throws \Exception
*/
- public function testGetMagentoModule()
+ public function testGetVendorAppCode()
{
- $modulePathExtractor = new ModulePathExtractor();
- $this->assertEquals(
- '[Analytics]',
- $modulePathExtractor->extractModuleName(
- self::MAGENTO_PATH
- )
- );
+ $mockPath = '/base/path/app/code/VendorB/ModuleB/Test/Mftf/Test/SomeTest.xml';
+
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup($this->mockTestModulePaths);
+ $extractor = new ModulePathExtractor();
+ $this->assertEquals('VendorB', $extractor->getExtensionPath($mockPath));
}
/**
- * Validate correct module is returned for extension path
+ * Validate module for dev/tests path
+ *
* @throws \Exception
*/
- public function testGetExtensionModule()
+ public function testGetModuleDevTests()
{
- $modulePathExtractor = new ModulePathExtractor();
- $this->assertEquals(
- '[Analytics]',
- $modulePathExtractor->extractModuleName(
- self::EXTENSION_PATH
- )
- );
+ $mockPath = '/base/path/dev/tests/acceptance/tests/functional/Magento/ModuleCTest/Test/SomeTest.xml';
+
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup($this->mockTestModulePaths);
+ $extractor = new ModulePathExtractor();
+ $this->assertEquals('ModuleC', $extractor->extractModuleName($mockPath));
}
/**
- * Validate Magento is returned for dev/tests/acceptance
+ * Validate vendor for dev/tests path
+ *
* @throws \Exception
*/
- public function testMagentoModulePath()
+ public function testGetVendorDevTests()
{
- $modulePathExtractor = new ModulePathExtractor();
- $this->assertEquals(
- 'Magento',
- $modulePathExtractor->getExtensionPath(
- self::MAGENTO_PATH
- )
- );
+ $mockPath = '/base/path/dev/tests/acceptance/tests/functional/VendorD/ModuleDTest/Test/SomeTest.xml';
+
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup($this->mockTestModulePaths);
+ $extractor = new ModulePathExtractor();
+ $this->assertEquals('VendorD', $extractor->getExtensionPath($mockPath));
}
/**
- * Validate correct extension path is returned
+ * Validate module with no _
+ *
* @throws \Exception
*/
- public function testExtensionModulePath()
+ public function testGetModule()
{
- $modulePathExtractor = new ModulePathExtractor();
- $this->assertEquals(
- 'TestExtension',
- $modulePathExtractor->getExtensionPath(
- self::EXTENSION_PATH
- )
- );
+ $mockPath = '/base/path/dev/tests/acceptance/tests/functional/FunctionalTest/SomeModuleE/Test/SomeTest.xml';
+
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup($this->mockTestModulePaths);
+ $extractor = new ModulePathExtractor();
+ $this->assertEquals('NO MODULE DETECTED', $extractor->extractModuleName($mockPath));
+ }
+
+ /**
+ * Validate module for vendor/tests path
+ *
+ * @throws \Exception
+ */
+ public function testGetModuleVendorDir()
+ {
+ $mockPath = '/base/path/vendor/magento/module-modulef/Test/Mftf/Test/SomeTest.xml';
+
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup($this->mockTestModulePaths);
+ $extractor = new ModulePathExtractor();
+ $this->assertEquals('ModuleF', $extractor->extractModuleName($mockPath));
+ }
+
+ /**
+ * Validate vendor for vendor path
+ *
+ * @throws \Exception
+ */
+ public function testGetVendorVendorDir()
+ {
+ $mockPath = '/base/path/vendor/vendorg/module-moduleg-test/Test/SomeTest.xml';
+
+ $resolverMock = new MockModuleResolverBuilder();
+ $resolverMock->setup($this->mockTestModulePaths);
+ $extractor = new ModulePathExtractor();
+ $this->assertEquals('VendorG', $extractor->getExtensionPath($mockPath));
}
}
diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModuleResolverTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModuleResolverTest.php
index 248704adc..6acf81b53 100644
--- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModuleResolverTest.php
+++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModuleResolverTest.php
@@ -68,6 +68,10 @@ public function testGetModulePathsAggregate()
$this->setMockResolverProperties($resolver, null, [0 => "Magento_example"]);
$this->assertEquals(
[
+ "example" . DIRECTORY_SEPARATOR . "paths",
+ "example" . DIRECTORY_SEPARATOR . "paths",
+ "example" . DIRECTORY_SEPARATOR . "paths",
+ "example" . DIRECTORY_SEPARATOR . "paths",
"example" . DIRECTORY_SEPARATOR . "paths",
"example" . DIRECTORY_SEPARATOR . "paths",
"example" . DIRECTORY_SEPARATOR . "paths"
@@ -82,6 +86,11 @@ public function testGetModulePathsAggregate()
*/
public function testGetModulePathsLocations()
{
+ // clear test object handler value to inject parsed content
+ $property = new \ReflectionProperty(ModuleResolver::class, 'instance');
+ $property->setAccessible(true);
+ $property->setValue(null);
+
$this->mockForceGenerate(false);
$mockResolver = $this->setMockResolverClass(
true,
@@ -94,6 +103,10 @@ public function testGetModulePathsLocations()
$this->setMockResolverProperties($resolver, null, null);
$this->assertEquals(
[
+ "example" . DIRECTORY_SEPARATOR . "paths",
+ "example" . DIRECTORY_SEPARATOR . "paths",
+ "example" . DIRECTORY_SEPARATOR . "paths",
+ "example" . DIRECTORY_SEPARATOR . "paths",
"example" . DIRECTORY_SEPARATOR . "paths",
"example" . DIRECTORY_SEPARATOR . "paths",
"example" . DIRECTORY_SEPARATOR . "paths"
@@ -107,18 +120,19 @@ public function testGetModulePathsLocations()
// Define the Module paths from default TESTS_MODULE_PATH
$modulePath = defined('TESTS_MODULE_PATH') ? TESTS_MODULE_PATH : TESTS_BP;
- $mockResolver->verifyInvoked('globRelevantPaths', [$modulePath, '']);
+ $mockResolver->verifyInvoked('globRelevantPaths', [$magentoBaseCodePath . '/vendor', 'Test/Mftf', null]);
+ $mockResolver->verifyInvoked('globRelevantPaths', [$magentoBaseCodePath . '/vendor', '*-test', 1]);
+ $mockResolver->verifyInvoked('globRelevantPaths', [$magentoBaseCodePath . '/app/code', 'Test/Mftf', null]);
$mockResolver->verifyInvoked(
'globRelevantPaths',
- [$magentoBaseCodePath . DIRECTORY_SEPARATOR . "vendor" , 'Test' . DIRECTORY_SEPARATOR .'Mftf']
+ [$magentoBaseCodePath . '/dev/tests/acceptance/tests/functional', '*Test', 1]
);
$mockResolver->verifyInvoked(
'globRelevantPaths',
- [
- $magentoBaseCodePath . DIRECTORY_SEPARATOR . "app" . DIRECTORY_SEPARATOR . "code",
- 'Test' . DIRECTORY_SEPARATOR .'Mftf'
- ]
+ [$magentoBaseCodePath . '/dev/tests/acceptance/tests/functional', 'FunctionalTest/*', 1]
);
+ $mockResolver->verifyInvoked('globRelevantPaths', [$modulePath, 'Test/Mftf', null]);
+ $mockResolver->verifyInvoked('globRelevantPaths', [$modulePath, '*', 0]);
}
/**
@@ -149,8 +163,8 @@ public function testGetModulePathsBlacklist()
null,
null,
null,
- function ($arg1, $arg2) {
- if ($arg2 === "") {
+ function ($arg1, $arg2, $arg3) {
+ if ($arg3 === null) {
$mockValue = ["somePath" => "somePath"];
} else {
$mockValue = ["lastPath" => "lastPath"];
@@ -160,7 +174,10 @@ function ($arg1, $arg2) {
);
$resolver = ModuleResolver::getInstance();
$this->setMockResolverProperties($resolver, null, null, ["somePath"]);
- $this->assertEquals(["lastPath", "lastPath"], $resolver->getModulesPath());
+ $this->assertEquals(
+ ["lastPath", "lastPath", "lastPath", "lastPath"],
+ $resolver->getModulesPath()
+ );
TestLoggingUtil::getInstance()->validateMockLogStatement(
'info',
'excluding module',
diff --git a/dev/tests/unit/Util/MockModuleResolverBuilder.php b/dev/tests/unit/Util/MockModuleResolverBuilder.php
new file mode 100644
index 000000000..706067f88
--- /dev/null
+++ b/dev/tests/unit/Util/MockModuleResolverBuilder.php
@@ -0,0 +1,57 @@
+ ['/base/path/app/code/Magento/Module/Test/Mftf']];
+
+ /**
+ * Mock ModuleResolver builder
+ *
+ * @param array $paths
+ * @return void
+ * @throws \Exception
+ */
+ public function setup($paths = null)
+ {
+ if (!empty($path)) {
+ $paths = $this->defaultPaths;
+ }
+
+ $mockConfig = AspectMock::double(MftfApplicationConfig::class, ['forceGenerateEnabled' => false]);
+ $instance = AspectMock::double(ObjectManager::class, ['create' => $mockConfig->make(), 'get' => null])->make();
+ AspectMock::double(ObjectManagerFactory::class, ['getObjectManager' => $instance]);
+
+ $property = new \ReflectionProperty(ModuleResolver::class, 'instance');
+ $property->setAccessible(true);
+ $property->setValue(null);
+
+ $mockResolver = AspectMock::double(
+ ModuleResolver::class,
+ ['getAdminToken' => false, 'globRelevantPaths' => [], 'getEnabledModules' => []]
+ );
+ $instance = AspectMock::double(ObjectManager::class, ['create' => $mockResolver->make(), 'get' => null])
+ ->make();
+ AspectMock::double(ObjectManagerFactory::class, ['getObjectManager' => $instance]);
+
+ $resolver = ModuleResolver::getInstance();
+ $property = new \ReflectionProperty(ModuleResolver::class, 'enabledModulePathsNoFlatten');
+ $property->setAccessible(true);
+ $property->setValue($resolver, $paths);
+ }
+}
diff --git a/dev/tests/verification/TestModule/Page/SamplePage.xml b/dev/tests/verification/TestModule/Page/SamplePage.xml
index bf8f99615..07494d88f 100644
--- a/dev/tests/verification/TestModule/Page/SamplePage.xml
+++ b/dev/tests/verification/TestModule/Page/SamplePage.xml
@@ -8,25 +8,25 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/src/Magento/FunctionalTestingFramework/Page/Config/Dom.php b/src/Magento/FunctionalTestingFramework/Page/Config/Dom.php
index bb6d08f58..a67cb1f1e 100644
--- a/src/Magento/FunctionalTestingFramework/Page/Config/Dom.php
+++ b/src/Magento/FunctionalTestingFramework/Page/Config/Dom.php
@@ -87,13 +87,13 @@ public function initDom($xml, $filename = null)
);
$pageNodes = $dom->getElementsByTagName('page');
$currentModule =
- $this->modulePathExtractor->extractModuleName($filename) .
- '_' .
- $this->modulePathExtractor->getExtensionPath($filename);
+ $this->modulePathExtractor->getExtensionPath($filename)
+ . '_'
+ . $this->modulePathExtractor->extractModuleName($filename);
foreach ($pageNodes as $pageNode) {
$pageModule = $pageNode->getAttribute("module");
$pageName = $pageNode->getAttribute("name");
- if ($pageModule !== $currentModule) {
+ if ($pageModule != $currentModule) {
if (MftfApplicationConfig::getConfig()->verboseEnabled()) {
print(
"Page Module does not match path Module. " .
diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php
index acad18572..f4eb7b5a7 100644
--- a/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php
+++ b/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php
@@ -11,6 +11,7 @@
use Magento\FunctionalTestingFramework\Test\Objects\ActionObject;
use Magento\FunctionalTestingFramework\Test\Objects\TestObject;
use Magento\FunctionalTestingFramework\Util\ModulePathExtractor;
+use Magento\FunctionalTestingFramework\Util\ModuleResolver;
use Magento\FunctionalTestingFramework\Util\Validation\NameValidationUtil;
/**
@@ -94,7 +95,8 @@ public function extractTestData($testData)
$filename = $testData['filename'] ?? null;
$fileNames = explode(",", $filename);
$baseFileName = $fileNames[0];
- $module = $this->modulePathExtractor->extractModuleName($baseFileName);
+ $module = ModuleResolver::getInstance()
+ ->trimTestModuleSuffix($this->modulePathExtractor->extractModuleName($baseFileName));
$testReference = $testData['extends'] ?? null;
$testActions = $this->stripDescriptorTags(
$testData,
diff --git a/src/Magento/FunctionalTestingFramework/Util/ModulePathExtractor.php b/src/Magento/FunctionalTestingFramework/Util/ModulePathExtractor.php
index 33e559ea8..c962782b1 100644
--- a/src/Magento/FunctionalTestingFramework/Util/ModulePathExtractor.php
+++ b/src/Magento/FunctionalTestingFramework/Util/ModulePathExtractor.php
@@ -11,41 +11,91 @@
*/
class ModulePathExtractor
{
- const MAGENTO = 'Magento';
+ const SPLIT_DELIMITER = '_';
+
+ /**
+ * Test module paths
+ *
+ * @var array
+ */
+ private $testModulePaths = [];
+
+ /**
+ * ModulePathExtractor constructor
+ */
+ public function __construct()
+ {
+ if (empty($this->testModulePaths)) {
+ $this->testModulePaths = ModuleResolver::getInstance()->getModulesPath(false);
+ }
+ }
/**
* Extracts module name from the path given
+ *
* @param string $path
* @return string
*/
public function extractModuleName($path)
{
- if (empty($path)) {
- return "NO MODULE DETECTED";
- }
- $paths = explode(DIRECTORY_SEPARATOR, $path);
- if (count($paths) < 3) {
+ $key = $this->extractKeyByPath($path);
+ if (empty($key)) {
return "NO MODULE DETECTED";
- } elseif ($paths[count($paths)-3] == "Mftf") {
- // app/code/Magento/[Analytics]/Test/Mftf/Test/SomeText.xml
- return $paths[count($paths)-5];
}
- // dev/tests/acceptance/tests/functional/Magento/FunctionalTest/[Analytics]/Test/SomeText.xml
- return $paths[count($paths)-3];
+ $parts = $this->splitKeyForParts($key);
+ return isset($parts[1]) ? $parts[1] : "NO MODULE DETECTED";
}
/**
- * Extracts the extension form the path, Magento for dev/tests/acceptance, [name] before module otherwise
+ * Extracts vendor name for module from the path given
+ *
* @param string $path
* @return string
*/
public function getExtensionPath($path)
{
+ $key = $this->extractKeyByPath($path);
+ if (empty($key)) {
+ return "NO VENDOR DETECTED";
+ }
+ $parts = $this->splitKeyForParts($key);
+ return isset($parts[0]) ? $parts[0] : "NO VENDOR DETECTED";
+ }
+
+ /**
+ * Split key by SPLIT_DELIMITER and return parts array
+ *
+ * @param string $key
+ * @return array
+ */
+ private function splitKeyForParts($key)
+ {
+ $parts = explode(self::SPLIT_DELIMITER, $key);
+ return count($parts) == 2 ? $parts : [];
+ }
+
+ /**
+ * Extract module name key by path
+ *
+ * @param string $path
+ * @return string
+ */
+ private function extractKeyByPath($path)
+ {
+ if (empty($path)) {
+ return '';
+ }
$paths = explode(DIRECTORY_SEPARATOR, $path);
- if ($paths[count($paths)-3] == "Mftf") {
- // app/code/[Magento]/Analytics/Test/Mftf/Test/SomeText.xml
- return $paths[count($paths)-6];
+ if (count($paths) < 3) {
+ return '';
+ }
+ $paths = array_slice($paths, 0, count($paths)-2);
+ $shortenedPath = implode(DIRECTORY_SEPARATOR, $paths);
+ foreach ($this->testModulePaths as $key => $pathArr) {
+ if (isset($pathArr[0]) && $pathArr[0] == $shortenedPath) {
+ return $key;
+ }
}
- return self::MAGENTO;
+ return '';
}
}
diff --git a/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php b/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php
index 16e6037fa..d7b4829cf 100644
--- a/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php
+++ b/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php
@@ -9,6 +9,7 @@
use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig;
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil;
+use Symfony\Component\Config\Resource\DirectoryResource;
use Symfony\Component\HttpFoundation\Response;
/**
@@ -38,6 +39,97 @@ class ModuleResolver
*/
const REGISTRAR_CLASS = "\Magento\Framework\Component\ComponentRegistrar";
+ /**
+ * const for vendor
+ */
+ const VENDOR = 'vendor';
+
+ /**
+ * const for app/code
+ */
+ const APP_CODE = 'app' . DIRECTORY_SEPARATOR . "code";
+
+ /**
+ * const for dev/tests/acceptance/tests/functional
+ */
+ const DEV_TEST = 'dev'
+ . DIRECTORY_SEPARATOR
+ . 'tests'
+ . DIRECTORY_SEPARATOR
+ . 'acceptance'
+ . DIRECTORY_SEPARATOR
+ . 'tests'
+ . DIRECTORY_SEPARATOR
+ . 'functional';
+
+ /**
+ * Vendor code path
+ */
+ const VENDOR_CODE_PATH = DIRECTORY_SEPARATOR . self::VENDOR;
+
+ /**
+ * App code path
+ */
+ const APP_CODE_PATH = DIRECTORY_SEPARATOR . self::APP_CODE;
+
+ /**
+ * Dev test code path
+ */
+ const DEV_TEST_CODE_PATH = DIRECTORY_SEPARATOR . self::DEV_TEST;
+
+ /**
+ * Pattern for Mftf directories
+ */
+ const MFTF_DIR_PATTERN = 'Test' . DIRECTORY_SEPARATOR . 'Mftf';
+
+ /**
+ * Regex to match an invalid dev test code path
+ */
+ const INVALID_DEV_TEST_CODE_PATH_REGEX = "~^[^:*\\?\"<>|']+"
+ . self::DEV_TEST_CODE_PATH
+ . "/[^/:*\\?\"<>|']+/"
+ . self::DEPRECATED_DEV_TEST_SHORT_NAME
+ . "$~";
+
+ /**
+ * Short directory name for deprecated path
+ */
+ const DEPRECATED_DEV_TEST_SHORT_NAME = 'FunctionalTest';
+
+ /**
+ * Regex to match deprecated dev test code path
+ */
+ const DEPRECATED_DEV_TEST_CODE_PATH_REGEX = "~^[^:*\\?\"<>|']+"
+ . self::DEV_TEST_CODE_PATH
+ . "/[^/:*\\?\"<>|']+/"
+ . self::DEPRECATED_DEV_TEST_SHORT_NAME
+ . "/[^:*\\?\"<>|']+~";
+
+ /**
+ * Test module name suffix
+ */
+ const TEST_MODULE_NAME_SUFFIX = 'Test';
+
+ /**
+ * Regex to match a test module name with suffix defined in TEST_MODULE_NAME_SUFFIX
+ */
+ const TEST_MODULE_NAME_REGEX = "~\S+" . self::TEST_MODULE_NAME_SUFFIX . "$~";
+
+ /**
+ * Regex to grab vendor name in vendor
+ */
+ const VENDOR_NAME_REGEX_V = "~.+\\/" . self::VENDOR . "\/(?<" . self::VENDOR . ">[^\/]+)\/.+~";
+
+ /**
+ * Regex to grab vendor name in app/code
+ */
+ const VENDOR_NAME_REGEX_A = "~.+\\/" . self::APP_CODE . "\/(?<" . self::VENDOR . ">[^\/]+)\/.+~";
+
+ /**
+ * Regex to grab vendor name dev/tests
+ */
+ const VENDOR_NAME_REGEX_D = "~.+\\/" . self::DEV_TEST . "\/(?<" . self::VENDOR . ">[^\/]+)\/.+~";
+
/**
* Enabled modules.
*
@@ -52,6 +144,13 @@ class ModuleResolver
*/
protected $enabledModulePaths = null;
+ /**
+ * Paths for non flattened enabled modules.
+ *
+ * @var array|null
+ */
+ protected $enabledModulePathsNoFlatten = null;
+
/**
* Configuration instance.
*
@@ -110,6 +209,13 @@ class ModuleResolver
'SampleTests', 'SampleTemplates'
];
+ /**
+ * Registered module list in magento instance being tested
+ *
+ * @var array
+ */
+ private $registeredModuleList = [];
+
/**
* Get ModuleResolver instance.
*
@@ -138,6 +244,7 @@ private function __construct()
* Return an array of enabled modules of target Magento instance.
*
* @return array
+ * @throws TestFrameworkException
*/
public function getEnabledModules()
{
@@ -179,32 +286,22 @@ public function getEnabledModules()
return $this->enabledModules;
}
- /**
- * Return an array of module whitelist that not exist in target Magento instance.
- *
- * @return array
- */
- protected function getModuleWhitelist()
- {
- $moduleWhitelist = getenv(self::MODULE_WHITELIST);
-
- if (empty($moduleWhitelist)) {
- return [];
- }
- return array_map('trim', explode(',', $moduleWhitelist));
- }
-
/**
* Return the modules path based on which modules are enabled in the target Magento instance.
*
+ * @param boolean $flat
* @return array
*/
- public function getModulesPath()
+ public function getModulesPath($flat = true)
{
- if (isset($this->enabledModulePaths)) {
+ if (isset($this->enabledModulePaths) && $flat) {
return $this->enabledModulePaths;
}
+ if (isset($this->enabledModulePathsNoFlatten) && !$flat) {
+ return $this->enabledModulePathsNoFlatten;
+ }
+
$allModulePaths = $this->aggregateTestModulePaths();
if (MftfApplicationConfig::getConfig()->forceGenerateEnabled()) {
@@ -219,10 +316,49 @@ public function getModulesPath()
return $this->enabledModulePaths;
}
+ /**
+ * Sort files according module sequence.
+ *
+ * @param array $files
+ * @return array
+ */
+ public function sortFilesByModuleSequence(array $files)
+ {
+ return $this->sequenceSorter->sort($files);
+ }
+
+ /**
+ * Trim test module suffix from module name
+ *
+ * @param string $moduleName
+ * @return string
+ */
+ public function trimTestModuleSuffix($moduleName)
+ {
+ preg_match(self::TEST_MODULE_NAME_REGEX, $moduleName, $match);
+ return empty($match) ? $moduleName : substr($moduleName, 0, -strlen(self::TEST_MODULE_NAME_SUFFIX));
+ }
+
+ /**
+ * Return an array of module whitelist that not exist in target Magento instance.
+ *
+ * @return array
+ */
+ protected function getModuleWhitelist()
+ {
+ $moduleWhitelist = getenv(self::MODULE_WHITELIST);
+
+ if (empty($moduleWhitelist)) {
+ return [];
+ }
+ return array_map('trim', explode(',', $moduleWhitelist));
+ }
+
/**
* Retrieves all module directories which might contain pertinent test code.
*
* @return array
+ * @throws TestFrameworkException
*/
private function aggregateTestModulePaths()
{
@@ -235,19 +371,71 @@ private function aggregateTestModulePaths()
$modulePath = defined('TESTS_MODULE_PATH') ? TESTS_MODULE_PATH : TESTS_BP;
$modulePath = rtrim($modulePath, DIRECTORY_SEPARATOR);
- $vendorCodePath = DIRECTORY_SEPARATOR . "vendor";
- $appCodePath = DIRECTORY_SEPARATOR . "app" . DIRECTORY_SEPARATOR . "code";
-
+ // Add known paths
$codePathsToPattern = [
- $modulePath => '',
- $magentoBaseCodePath . $vendorCodePath => 'Test' . DIRECTORY_SEPARATOR . 'Mftf',
- $magentoBaseCodePath . $appCodePath => 'Test' . DIRECTORY_SEPARATOR . 'Mftf'
+ $magentoBaseCodePath . self::VENDOR_CODE_PATH => [
+ [
+ 'pattern' => 'Test' . DIRECTORY_SEPARATOR . 'Mftf',
+ 'level' => null
+ ],
+ [
+ 'pattern' => '*-test',
+ 'level' => 1
+ ]
+ ],
+ $magentoBaseCodePath . self::APP_CODE_PATH => [
+ [
+ 'pattern' => 'Test' . DIRECTORY_SEPARATOR . 'Mftf',
+ 'level' => null
+ ]
+ ],
+ $magentoBaseCodePath . self::DEV_TEST_CODE_PATH => [
+ [
+ 'pattern' => '*' . self::TEST_MODULE_NAME_SUFFIX,
+ 'level' => 1
+ ],
+ [
+ 'pattern' => self::DEPRECATED_DEV_TEST_SHORT_NAME . DIRECTORY_SEPARATOR . '*',
+ 'level' => 1
+ ]
+ ]
];
- foreach ($codePathsToPattern as $codePath => $pattern) {
- $allModulePaths = array_merge_recursive($allModulePaths, $this->globRelevantPaths($codePath, $pattern));
+ // Check if module path is a known path
+ $newPath = true;
+ foreach (array_keys($codePathsToPattern) as $key) {
+ if (strpos($modulePath, $key) !== false) {
+ $newPath = false;
+ }
+ }
+
+ // Add module path if it's a new path
+ if ($newPath) {
+ $codePathsToPattern[$modulePath] = [
+ [
+ 'pattern' => '*',
+ 'level' => 0
+ ],
+ [
+ 'pattern' => 'Test' . DIRECTORY_SEPARATOR . 'Mftf',
+ 'level' => null
+ ]
+ ];
+ }
+
+ // Glob pattern for relevant paths
+ foreach ($codePathsToPattern as $codePath => $patterns) {
+ foreach ($patterns as $pattern) {
+ $allModulePaths = array_merge_recursive(
+ $allModulePaths,
+ $this->globRelevantPaths($codePath, $pattern['pattern'], $pattern['level'])
+ );
+ }
}
+ // Validate module paths
+ $this->validateModulePaths($allModulePaths);
+
return $allModulePaths;
}
@@ -256,37 +444,50 @@ private function aggregateTestModulePaths()
* are returned as an associative array keyed by basename (the last dir excluding pattern) to an array containing
* the matching path.
*
- * @param string $testPath
- * @param string $pattern
+ * @param string $testPath
+ * @param string $pattern
+ * @param integer $level
* @return array
*/
- private function globRelevantPaths($testPath, $pattern)
+ private function globRelevantPaths($testPath, $pattern, $level)
{
$modulePaths = [];
$relevantPaths = [];
if (file_exists($testPath)) {
- $relevantPaths = $this->globRelevantWrapper($testPath, $pattern);
+ $relevantPaths = $this->globRelevantWrapper($testPath, $pattern, $level);
}
$allComponents = $this->getRegisteredModuleList();
foreach ($relevantPaths as $codePath) {
- // Reduce magento/app/code/Magento/AdminGws/ to magento/app/code/Magento/AdminGws to read symlink
+ $possibleVendorName = $this->getPossibleVendorName($codePath);
+
+ // Reduce magento/app/code/Magento/AdminGws/Test/MFTF to magento/app/code/Magento/AdminGws to read symlink
// Symlinks must be resolved otherwise they will not match Magento's filepath to the module
- $potentialSymlink = str_replace(DIRECTORY_SEPARATOR . $pattern, "", $codePath);
- if (is_link($potentialSymlink)) {
- $codePath = realpath($potentialSymlink) . DIRECTORY_SEPARATOR . $pattern;
+ if ($pattern == self::MFTF_DIR_PATTERN) {
+ $codePath = str_replace(DIRECTORY_SEPARATOR . self::MFTF_DIR_PATTERN, "", $codePath);
+ }
+ if (is_link($codePath)) {
+ $codePath = realpath($codePath);
}
- $mainModName = array_search($codePath, $allComponents) ?: basename(str_replace($pattern, '', $codePath));
- $modulePaths[$mainModName][] = $codePath;
-
- if (MftfApplicationConfig::getConfig()->verboseEnabled()) {
- LoggingUtil::getInstance()->getLogger(ModuleResolver::class)->debug(
- "including module",
- ['module' => $mainModName, 'path' => $codePath]
- );
+ $mainModName = array_search($codePath, $allComponents) ?: $possibleVendorName . '_' . basename($codePath);
+
+ preg_match(self::INVALID_DEV_TEST_CODE_PATH_REGEX, $codePath, $match);
+ if (empty($match)) {
+ if ($pattern == self::MFTF_DIR_PATTERN) {
+ $modulePaths[$mainModName][] = $codePath . DIRECTORY_SEPARATOR . self::MFTF_DIR_PATTERN;
+ } else {
+ $modulePaths[$mainModName][] = $codePath;
+ }
+
+ if (MftfApplicationConfig::getConfig()->verboseEnabled()) {
+ LoggingUtil::getInstance()->getLogger(ModuleResolver::class)->debug(
+ "including module",
+ ['module' => $mainModName, 'path' => $codePath]
+ );
+ }
}
}
@@ -295,18 +496,25 @@ private function globRelevantPaths($testPath, $pattern)
/**
* Glob wrapper for globRelevantPaths function
+ * When $level = null, it's recursion
*
- * @param string $testPath
- * @param string $pattern
+ * @param string $testPath
+ * @param string $pattern
+ * @param integer $level
* @return array
*/
- private static function globRelevantWrapper($testPath, $pattern)
+ private static function globRelevantWrapper($testPath, $pattern, $level = null)
{
- if ($pattern == "") {
- return glob($testPath . '*' . DIRECTORY_SEPARATOR . '*' . $pattern);
+ $subDirectory = DIRECTORY_SEPARATOR . "*";
+ if ($level !== null) {
+ $subDirectories = '';
+ for ($i = 0; $i < $level; $i++) {
+ $subDirectories .= $subDirectory;
+ }
+ return glob($testPath . $subDirectories . DIRECTORY_SEPARATOR . $pattern, GLOB_ONLYDIR);
}
- $subDirectory = "*" . DIRECTORY_SEPARATOR;
- $directories = glob($testPath . $subDirectory . $pattern, GLOB_ONLYDIR);
+
+ $directories = glob($testPath . $subDirectory . DIRECTORY_SEPARATOR . $pattern, GLOB_ONLYDIR);
foreach (glob($testPath . $subDirectory, GLOB_ONLYDIR) as $dir) {
$directories = array_merge_recursive($directories, self::globRelevantWrapper($dir, $pattern));
}
@@ -341,16 +549,19 @@ private function getEnabledDirectoryPaths($enabledModules, $allModulePaths)
{
$enabledDirectoryPaths = [];
foreach ($enabledModules as $magentoModuleName) {
- if (!isset($this->knownDirectories[$magentoModuleName]) && !isset($allModulePaths[$magentoModuleName])) {
- continue;
- } elseif (isset($this->knownDirectories[$magentoModuleName])
- && !isset($allModulePaths[$magentoModuleName])) {
+ $magentoTestModuleName = $magentoModuleName . self::TEST_MODULE_NAME_SUFFIX;
+ if (isset($this->knownDirectories[$magentoModuleName]) && !isset($allModulePaths[$magentoModuleName])) {
LoggingUtil::getInstance()->getLogger(ModuleResolver::class)->warn(
"Known directory could not match to an existing path.",
['knownDirectory' => $magentoModuleName]
);
} else {
- $enabledDirectoryPaths[$magentoModuleName] = $allModulePaths[$magentoModuleName];
+ if (isset($allModulePaths[$magentoModuleName])) {
+ $enabledDirectoryPaths[$magentoModuleName] = $allModulePaths[$magentoModuleName];
+ }
+ if (isset($allModulePaths[$magentoTestModuleName])) {
+ $enabledDirectoryPaths[$magentoTestModuleName] = $allModulePaths[$magentoTestModuleName];
+ }
}
}
return $enabledDirectoryPaths;
@@ -447,17 +658,6 @@ protected function getAdminToken()
return json_decode($response);
}
- /**
- * Sort files according module sequence.
- *
- * @param array $files
- * @return array
- */
- public function sortFilesByModuleSequence(array $files)
- {
- return $this->sequenceSorter->sort($files);
- }
-
/**
* A wrapping method for any custom logic which needs to be applied to the module list
*
@@ -476,6 +676,9 @@ protected function applyCustomModuleMethods($modulesPath)
);
}, $customModulePaths);
+ if (!isset($this->enabledModulePathsNoFlatten)) {
+ $this->enabledModulePathsNoFlatten = array_merge($modulePathsResult, $customModulePaths);
+ }
return $this->flattenAllModulePaths(array_merge($modulePathsResult, $customModulePaths));
}
@@ -489,12 +692,23 @@ private function removeBlacklistModules($modulePaths)
{
$modulePathsResult = $modulePaths;
foreach ($modulePathsResult as $moduleName => $modulePath) {
+ // Remove module if it is in blacklist
if (in_array($moduleName, $this->getModuleBlacklist())) {
unset($modulePathsResult[$moduleName]);
LoggingUtil::getInstance()->getLogger(ModuleResolver::class)->info(
"excluding module",
['module' => $moduleName]
);
+ } else {
+ // Remove test module if its magento module is in blacklist
+ $relatedModuleName = $this->trimTestModuleSuffix($moduleName);
+ if (($relatedModuleName != $moduleName) && in_array($relatedModuleName, $this->getModuleBlacklist())) {
+ unset($modulePathsResult[$moduleName]);
+ LoggingUtil::getInstance()->getLogger(ModuleResolver::class)->info(
+ "excluding module",
+ ['module' => $moduleName]
+ );
+ }
}
}
@@ -534,6 +748,10 @@ private function getModuleBlacklist()
*/
private function getRegisteredModuleList()
{
+ if (!empty($this->registeredModuleList)) {
+ return $this->registeredModuleList;
+ }
+
if (array_key_exists('MAGENTO_BP', $_ENV)) {
$autoloadPath = realpath(MAGENTO_BP . "/app/autoload.php");
if ($autoloadPath) {
@@ -545,20 +763,22 @@ private function getRegisteredModuleList()
}
try {
- $allComponents = [];
+ $this->registeredModuleList = [];
if (!class_exists(self::REGISTRAR_CLASS)) {
throw new TestFrameworkException("Magento Installation not found when loading registered modules.\n");
}
$components = new \Magento\Framework\Component\ComponentRegistrar();
foreach (self::PATHS as $componentType) {
- $allComponents = array_merge($allComponents, $components->getPaths($componentType));
+ $this->registeredModuleList = array_merge(
+ $this->registeredModuleList,
+ $components->getPaths($componentType)
+ );
}
- array_walk($allComponents, function (&$value) {
+ array_walk($this->registeredModuleList, function (&$value) {
// Magento stores component paths with unix DIRECTORY_SEPARATOR, need to stay uniform and convert
$value = realpath($value);
- $value .= '/Test/Mftf';
});
- return $allComponents;
+ return $this->registeredModuleList;
} catch (TestFrameworkException $e) {
LoggingUtil::getInstance()->getLogger(ModuleResolver::class)->warning(
"$e"
@@ -575,4 +795,86 @@ private function getBackendUrl()
{
return getenv('MAGENTO_BACKEND_BASE_URL') ?: getenv('MAGENTO_BASE_URL');
}
+
+ /**
+ * Validate module paths for violation and deprecations
+ *
+ * @param array $modulePaths
+ * @return void
+ * @throws TestFrameworkException
+ */
+ private function validateModulePaths($modulePaths)
+ {
+ $foundDeprecate = false;
+ // Check tests should be in one location per module
+ foreach ($modulePaths as $moduleName => $modulePath) {
+ // Check tests in deprecated path
+ if (!$foundDeprecate) {
+ preg_match(self::DEPRECATED_DEV_TEST_CODE_PATH_REGEX, $modulePath[0], $match);
+ if (!empty($match)) {
+ $foundDeprecate = true;
+ }
+ }
+ $relatedModuleName = $this->trimTestModuleSuffix($moduleName);
+ if (($relatedModuleName != $moduleName) && isset($modulePaths[$relatedModuleName])) {
+ $message = "Mftf tests cannot be in both $moduleName and $relatedModuleName modules. "
+ . "Please move all mftf tests to $relatedModuleName.";
+ throw new TestFrameworkException($message);
+ }
+ }
+
+ if ($foundDeprecate) {
+ $deprecaedPath = ltrim(
+ self::DEV_TEST_CODE_PATH
+ . DIRECTORY_SEPARATOR
+ . ''
+ . DIRECTORY_SEPARATOR
+ . self::DEPRECATED_DEV_TEST_SHORT_NAME
+ . DIRECTORY_SEPARATOR,
+ '/'
+ );
+
+ $suggestedPath = ltrim(
+ self::DEV_TEST_CODE_PATH
+ . DIRECTORY_SEPARATOR
+ . ''
+ . DIRECTORY_SEPARATOR,
+ '/'
+ );
+
+ // Suppress print during unit testing
+ if (MftfApplicationConfig::getConfig()->getPhase() !== MftfApplicationConfig::UNIT_TEST_PHASE) {
+ LoggingUtil::getInstance()->getLogger(ModuleResolver::class)->warning(
+ "DEPRECATION: $deprecaedPath is deprecated! Please move mftf test modules to $suggestedPath"
+ );
+ print ("\nDEPRECATION: $deprecaedPath is deprecated! Please move mftf tests to $suggestedPath\n\n");
+ }
+ }
+ }
+
+ /**
+ * Return possible vendor name from a path given
+ *
+ * @param string $path
+ * @return string
+ */
+ private function getPossibleVendorName($path)
+ {
+ $possibleVendorName = 'Unknown';
+ $regexs = [
+ self::VENDOR_NAME_REGEX_A,
+ self::VENDOR_NAME_REGEX_D,
+ self::VENDOR_NAME_REGEX_V
+ ];
+
+ foreach ($regexs as $regex) {
+ $match = [];
+ preg_match($regex, $path, $match);
+ if (isset($match[self::VENDOR])) {
+ $possibleVendorName = ucfirst($match[self::VENDOR]);
+ return $possibleVendorName;
+ }
+ }
+ return $possibleVendorName;
+ }
}