Skip to content

Commit 7ac812b

Browse files
committed
MQE-1257: MFTF Troubleshoot command
1 parent c3f7c05 commit 7ac812b

File tree

7 files changed

+218
-21
lines changed

7 files changed

+218
-21
lines changed

dev/tests/functional/standalone_bootstrap.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515

1616
require_once realpath(PROJECT_ROOT . '/vendor/autoload.php');
1717

18+
$envFilePath = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR;
19+
defined('ENV_FILE_PATH') || define('ENV_FILE_PATH', $envFilePath);
20+
1821
//Load constants from .env file
19-
$envFilePath = dirname(dirname(__DIR__));
20-
if (file_exists($envFilePath . DIRECTORY_SEPARATOR . '.env')) {
21-
$env = new \Dotenv\Loader($envFilePath . DIRECTORY_SEPARATOR . '.env');
22+
if (file_exists(ENV_FILE_PATH . '.env')) {
23+
$env = new \Dotenv\Loader(ENV_FILE_PATH . '.env');
2224
$env->load();
2325

2426
foreach ($_ENV as $key => $var) {

src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ class MftfApplicationConfig
1515
const GENERATION_PHASE = "generation";
1616
const EXECUTION_PHASE = "execution";
1717
const UNIT_TEST_PHASE = "testing";
18-
const MFTF_PHASES = [self::GENERATION_PHASE, self::EXECUTION_PHASE, self::UNIT_TEST_PHASE];
18+
const DIAGNOSTIC_PHASE = "diagnostic";
19+
const MFTF_PHASES = [self::GENERATION_PHASE, self::EXECUTION_PHASE, self::UNIT_TEST_PHASE, self::DIAGNOSTIC_PHASE];
1920

2021
/**
2122
* Mftf debug levels

src/Magento/FunctionalTestingFramework/Console/CommandList.php

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,20 @@ class CommandList implements CommandListInterface
2929
public function __construct(array $commands = [])
3030
{
3131
$this->commands = [
32-
'build:project' => new BuildProjectCommand(),
33-
'reset' => new CleanProjectCommand(),
34-
'generate:urn-catalog' => new GenerateDevUrnCommand(),
35-
'generate:suite' => new GenerateSuiteCommand(),
36-
'generate:tests' => new GenerateTestsCommand(),
37-
'run:test' => new RunTestCommand(),
38-
'run:group' => new RunTestGroupCommand(),
39-
'run:failed' => new RunTestFailedCommand(),
40-
'run:manifest' => new RunManifestCommand(),
41-
'setup:env' => new SetupEnvCommand(),
42-
'upgrade:tests' => new UpgradeTestsCommand(),
43-
'generate:docs' => new GenerateDocsCommand(),
44-
'static-checks' => new StaticChecksCommand()
32+
'build:project' => new BuildProjectCommand(),
33+
'generate:docs' => new GenerateDocsCommand(),
34+
'generate:suite' => new GenerateSuiteCommand(),
35+
'generate:tests' => new GenerateTestsCommand(),
36+
'generate:urn-catalog' => new GenerateDevUrnCommand(),
37+
'reset' => new CleanProjectCommand(),
38+
'run:failed' => new RunTestFailedCommand(),
39+
'run:group' => new RunTestGroupCommand(),
40+
'run:manifest' => new RunManifestCommand(),
41+
'run:test' => new RunTestCommand(),
42+
'setup:env' => new SetupEnvCommand(),
43+
'static-checks' => new StaticChecksCommand(),
44+
'troubleshoot' => new TroubleShootCommand(),
45+
'upgrade:tests' => new UpgradeTestsCommand(),
4546
] + $commands;
4647
}
4748

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types = 1);
7+
8+
namespace Magento\FunctionalTestingFramework\Console;
9+
10+
use Codeception\Configuration;
11+
use Symfony\Component\EventDispatcher\EventDispatcher;
12+
use Codeception\SuiteManager;
13+
use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig;
14+
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
15+
use Symfony\Component\Console\Command\Command;
16+
use Symfony\Component\Console\Input\InputInterface;
17+
use Symfony\Component\Console\Output\OutputInterface;
18+
use Magento\FunctionalTestingFramework\Util\ModuleResolver;
19+
20+
class TroubleShootCommand extends Command
21+
{
22+
const CODECEPTION_AUTOLOAD_FILE = PROJECT_ROOT . '/vendor/codeception/codeception/autoload.php';
23+
const MFTF_CODECEPTION_CONFIG_FILE = ENV_FILE_PATH . 'codeception.yml';
24+
const SUITE = 'functional';
25+
const REQUIRED_PHP_EXTS = ['CURL', 'mbstring', 'bcmath', 'zip', 'dom', 'gd', 'intl'];
26+
27+
/**
28+
* Command Output
29+
*
30+
* @var OutputInterface
31+
*/
32+
private $output;
33+
34+
/**
35+
* Configures the current command.
36+
*
37+
* @return void
38+
*/
39+
protected function configure()
40+
{
41+
$this->setName('troubleshoot')
42+
->setDescription(
43+
'This command checks environment readiness for generating and running MFTF tests.'
44+
);
45+
}
46+
47+
/**
48+
* Executes the current command.
49+
*
50+
* @param InputInterface $input
51+
* @param OutputInterface $output
52+
* @return void
53+
* @throws TestFrameworkException
54+
*/
55+
protected function execute(InputInterface $input, OutputInterface $output)
56+
{
57+
$cmdStatus = true;
58+
59+
// Config application
60+
$verbose = $output->isVerbose();
61+
$this->output = $output;
62+
MftfApplicationConfig::create(
63+
false,
64+
MftfApplicationConfig::DIAGNOSTIC_PHASE,
65+
$verbose,
66+
MftfApplicationConfig::LEVEL_DEVELOPER,
67+
false
68+
);
69+
70+
// Check required PHP extensions
71+
foreach (self::REQUIRED_PHP_EXTS as $ext) {
72+
$status = $this->checkPhpExtIsAvailable($ext);
73+
$cmdStatus = $cmdStatus && !$status ? false : $cmdStatus;
74+
}
75+
76+
// Check authentication to Magento Admin
77+
$status = $this->checkAuthenticationToMagentoAdmin();
78+
$cmdStatus = $cmdStatus && !$status ? false : $cmdStatus;
79+
80+
// Check connectivity and authentication to Magento Admin
81+
$status = $this->checkConnectivityToSeleniumServer();
82+
$cmdStatus = $cmdStatus && !$status ? false : $cmdStatus;
83+
84+
if ($cmdStatus) {
85+
exit(0);
86+
} else {
87+
exit(1);
88+
}
89+
}
90+
91+
/**
92+
* Check php extention is installed and available
93+
*
94+
* @param string $ext
95+
* @return boolean
96+
*/
97+
private function checkPhpExtIsAvailable($ext)
98+
{
99+
$result = false;
100+
$this->output->writeln("\nChecking PHP extenstion \"{$ext}\" ...");
101+
if (extension_loaded(strtolower($ext))) {
102+
$this->output->writeln('Successful');
103+
$result = true;
104+
} else {
105+
$this->output->writeln(
106+
"MFTF requires \"{$ext}\" extension installed to make tests run\n"
107+
. "Please make sure that the PHP you run has \"{$ext}\" installed and enabled."
108+
);
109+
}
110+
return $result;
111+
}
112+
113+
/**
114+
* Check authentication to Magento Admin
115+
*
116+
* @return boolean
117+
*/
118+
private function checkAuthenticationToMagentoAdmin()
119+
{
120+
$result = false;
121+
try {
122+
$this->output->writeln("\nChecking authentication to Magento Admin ...");
123+
ModuleResolver::getInstance()->getAdminToken();
124+
$this->output->writeln('Successful');
125+
$result = true;
126+
} catch (TestFrameworkException $e) {
127+
$this->output->writeln($e->getMessage());
128+
}
129+
return $result;
130+
}
131+
132+
/**
133+
* Check Connectivity to Selenium Server
134+
*
135+
* @return boolean
136+
*/
137+
private function checkConnectivityToSeleniumServer()
138+
{
139+
$result = false;
140+
141+
// Check connectivity to Selenium through Codeception
142+
$this->output->writeln("\nChecking connectivity to Selenium Server ...");
143+
require_once realpath(self::CODECEPTION_AUTOLOAD_FILE);
144+
145+
$config = Configuration::config(realpath(self::MFTF_CODECEPTION_CONFIG_FILE));
146+
$settings = Configuration::suiteSettings(self::SUITE, $config);
147+
$dispatcher = new EventDispatcher();
148+
$suiteManager = new SuiteManager($dispatcher, self::SUITE, $settings);
149+
try {
150+
$suiteManager->initialize();
151+
$this->output->writeln('Successful');
152+
$result = true;
153+
} catch (TestFrameworkException $e) {
154+
$this->output->writeln($e->getMessage());
155+
}
156+
return $result;
157+
}
158+
}

src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
use Symfony\Component\Process\Process;
2424
use Yandex\Allure\Adapter\Support\AttachmentSupport;
2525
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
26+
use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig;
27+
use Facebook\WebDriver\Remote\RemoteWebDriver;
28+
use Facebook\WebDriver\Exception\WebDriverCurlException;
2629

2730
/**
2831
* MagentoWebDriver module provides common Magento web actions through Selenium WebDriver.
@@ -126,6 +129,11 @@ public function _initialize()
126129
$this->config = ConfigSanitizerUtil::sanitizeWebDriverConfig($this->config);
127130
parent::_initialize();
128131
$this->cleanJsError();
132+
133+
// Check Selenium Server readiness if it's in diagnostic phase
134+
if (MftfApplicationConfig::getConfig()->getPhase() === MftfApplicationConfig::DIAGNOSTIC_PHASE) {
135+
$this->checkSeleniumServerReadiness();
136+
}
129137
}
130138

131139
/**
@@ -826,6 +834,31 @@ public function makeScreenshot($name = null)
826834
AllureHelper::addAttachmentToCurrentStep($screenName, 'Screenshot');
827835
}
828836

837+
/**
838+
* Check connectivity to running selenium server
839+
*
840+
* @return void
841+
* @throws TestFrameworkException
842+
*/
843+
public function checkSeleniumServerReadiness()
844+
{
845+
try {
846+
RemoteWebDriver::create(
847+
$this->wdHost,
848+
$this->capabilities,
849+
$this->connectionTimeoutInMs,
850+
$this->requestTimeoutInMs,
851+
$this->httpProxy,
852+
$this->httpProxyPort
853+
);
854+
} catch (WebDriverCurlException $e) {
855+
throw new TestFrameworkException(
856+
"Can't connect to Webdriver at {$this->wdHost}.\n"
857+
. "Please make sure that Selenium Server is running."
858+
);
859+
}
860+
}
861+
829862
/**
830863
* Takes given $command and executes it against bin/magento executable. Returns stdout output from the command.
831864
*

src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ private function printMagentoVersionInfo()
703703
*
704704
* @return string|boolean
705705
*/
706-
protected function getAdminToken()
706+
public function getAdminToken()
707707
{
708708
$login = $_ENV['MAGENTO_ADMIN_USERNAME'] ?? null;
709709
$password = $_ENV['MAGENTO_ADMIN_PASSWORD'] ?? null;

src/Magento/FunctionalTestingFramework/_bootstrap.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
return;
1616
}
1717
defined('PROJECT_ROOT') || define('PROJECT_ROOT', $projectRootPath);
18-
$envFilepath = realpath($projectRootPath . '/dev/tests/acceptance/');
1918

19+
$envFilePath = realpath($projectRootPath . '/dev/tests/acceptance/');
20+
defined('ENV_FILE_PATH') || define('ENV_FILE_PATH', $envFilePath);
2021

21-
if (file_exists($envFilepath . DIRECTORY_SEPARATOR . '.env')) {
22-
$env = new \Dotenv\Loader($envFilepath . DIRECTORY_SEPARATOR . '.env');
22+
//Load constants from .env file
23+
if (file_exists(ENV_FILE_PATH . '.env')) {
24+
$env = new \Dotenv\Loader(ENV_FILE_PATH . '.env');
2325
$env->load();
2426

2527
if (array_key_exists('TESTS_MODULE_PATH', $_ENV) xor array_key_exists('TESTS_BP', $_ENV)) {

0 commit comments

Comments
 (0)