Skip to content

Commit f1299b1

Browse files
committed
MQE-1257: MFTF doctor command
1 parent 4fdf441 commit f1299b1

File tree

6 files changed

+188
-75
lines changed

6 files changed

+188
-75
lines changed

src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php

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

2120
/**
2221
* Mftf debug levels

src/Magento/FunctionalTestingFramework/Console/CommandList.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public function __construct(array $commands = [])
3030
{
3131
$this->commands = [
3232
'build:project' => new BuildProjectCommand(),
33+
'doctor' => new DoctorCommand(),
3334
'generate:docs' => new GenerateDocsCommand(),
3435
'generate:suite' => new GenerateSuiteCommand(),
3536
'generate:tests' => new GenerateTestsCommand(),
@@ -41,7 +42,6 @@ public function __construct(array $commands = [])
4142
'run:test' => new RunTestCommand(),
4243
'setup:env' => new SetupEnvCommand(),
4344
'static-checks' => new StaticChecksCommand(),
44-
'troubleshoot' => new TroubleShootCommand(),
4545
'upgrade:tests' => new UpgradeTestsCommand(),
4646
] + $commands;
4747
}

src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php renamed to src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php

Lines changed: 81 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616
use Symfony\Component\Console\Input\InputInterface;
1717
use Symfony\Component\Console\Output\OutputInterface;
1818
use Magento\FunctionalTestingFramework\Util\ModuleResolver;
19+
use Magento\FunctionalTestingFramework\Module\MagentoWebDriver;
20+
use Magento\FunctionalTestingFramework\Module\MagentoWebDriverDoctor;
1921

20-
class TroubleShootCommand extends Command
22+
class DoctorCommand extends Command
2123
{
2224
const CODECEPTION_AUTOLOAD_FILE = PROJECT_ROOT . '/vendor/codeception/codeception/autoload.php';
2325
const MFTF_CODECEPTION_CONFIG_FILE = ENV_FILE_PATH . 'codeception.yml';
2426
const SUITE = 'functional';
25-
const REQUIRED_PHP_EXTS = ['CURL', 'mbstring', 'bcmath', 'zip', 'dom', 'gd', 'intl'];
2627

2728
/**
2829
* Command Output
@@ -31,14 +32,21 @@ class TroubleShootCommand extends Command
3132
*/
3233
private $output;
3334

35+
/**
36+
* Exception Context
37+
*
38+
* @var array
39+
*/
40+
private $context = [];
41+
3442
/**
3543
* Configures the current command.
3644
*
3745
* @return void
3846
*/
3947
protected function configure()
4048
{
41-
$this->setName('troubleshoot')
49+
$this->setName('doctor')
4250
->setDescription(
4351
'This command checks environment readiness for generating and running MFTF tests.'
4452
);
@@ -62,24 +70,22 @@ protected function execute(InputInterface $input, OutputInterface $output)
6270
$this->output = $output;
6371
MftfApplicationConfig::create(
6472
false,
65-
MftfApplicationConfig::DIAGNOSTIC_PHASE,
73+
MftfApplicationConfig::GENERATION_PHASE,
6674
$verbose,
6775
MftfApplicationConfig::LEVEL_DEVELOPER,
6876
false
6977
);
7078

71-
// Check required PHP extensions
72-
foreach (self::REQUIRED_PHP_EXTS as $ext) {
73-
$status = $this->checkPhpExtIsAvailable($ext);
74-
$cmdStatus = $cmdStatus && !$status ? false : $cmdStatus;
75-
}
76-
7779
// Check authentication to Magento Admin
7880
$status = $this->checkAuthenticationToMagentoAdmin();
7981
$cmdStatus = $cmdStatus && !$status ? false : $cmdStatus;
8082

81-
// Check connectivity and authentication to Magento Admin
82-
$status = $this->checkConnectivityToSeleniumServer();
83+
// Check connection to Selenium
84+
$status = $this->checkConnectionToSeleniumServer();
85+
$cmdStatus = $cmdStatus && !$status ? false : $cmdStatus;
86+
87+
// Check access to Magento CLI
88+
$status = $this->checkAccessToMagentoCLI();
8389
$cmdStatus = $cmdStatus && !$status ? false : $cmdStatus;
8490

8591
if ($cmdStatus) {
@@ -90,70 +96,104 @@ protected function execute(InputInterface $input, OutputInterface $output)
9096
}
9197

9298
/**
93-
* Check php extention is installed and available
99+
* Check authentication to Magento Admin
94100
*
95-
* @param string $ext
96101
* @return boolean
97102
*/
98-
private function checkPhpExtIsAvailable($ext)
103+
private function checkAuthenticationToMagentoAdmin()
99104
{
100105
$result = false;
101-
$this->output->writeln("\nChecking PHP extenstion \"{$ext}\" ...");
102-
if (extension_loaded(strtolower($ext))) {
106+
try {
107+
$this->output->writeln("\nChecking authentication to Magento Admin ...");
108+
ModuleResolver::getInstance()->getAdminToken();
103109
$this->output->writeln('Successful');
104110
$result = true;
105-
} else {
106-
$this->output->writeln(
107-
"MFTF requires \"{$ext}\" extension installed to make tests run\n"
108-
. "Please make sure that the PHP you run has \"{$ext}\" installed and enabled."
109-
);
111+
} catch (TestFrameworkException $e) {
112+
$this->output->writeln($e->getMessage());
110113
}
111114
return $result;
112115
}
113116

114117
/**
115-
* Check authentication to Magento Admin
118+
* Check Connection to Selenium Server
116119
*
117120
* @return boolean
118121
*/
119-
private function checkAuthenticationToMagentoAdmin()
122+
private function checkConnectionToSeleniumServer()
120123
{
121-
$result = false;
122-
try {
123-
$this->output->writeln("\nChecking authentication to Magento Admin ...");
124-
ModuleResolver::getInstance()->getAdminToken();
124+
// Check connection to Selenium through Codeception
125+
$this->output->writeln("\nChecking connection to Selenium Server ...");
126+
$this->runMagentoWebDriverDoctor();
127+
128+
if (isset($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_SELENIUM])) {
129+
$this->output->write($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_SELENIUM] . "\n");
130+
return false;
131+
} else {
125132
$this->output->writeln('Successful');
126-
$result = true;
127-
} catch (TestFrameworkException $e) {
128-
$this->output->writeln($e->getMessage());
133+
return true;
129134
}
130-
return $result;
131135
}
132136

133137
/**
134-
* Check Connectivity to Selenium Server
138+
* Check access to Magento CLI setup
135139
*
136140
* @return boolean
137141
*/
138-
private function checkConnectivityToSeleniumServer()
142+
private function checkAccessToMagentoCLI()
139143
{
140-
$result = false;
144+
// Check Magento CLI setup
145+
$this->output->writeln("\nChecking access to Magento CLI ...");
146+
$this->runMagentoWebDriverDoctor();
147+
148+
if (isset($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_MAGENTO_CLI])) {
149+
$this->output->write($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_MAGENTO_CLI] . "\n");
150+
return false;
151+
} else {
152+
$this->output->writeln('Successful');
153+
return true;
154+
}
155+
}
156+
157+
/**
158+
* Run diagnose through MagentoWebDriverDoctor
159+
*
160+
* @return void
161+
*/
162+
private function runMagentoWebDriverDoctor()
163+
{
164+
if (!empty($this->context)) {
165+
return;
166+
}
167+
168+
$magentoWebDriver = '\\' . MagentoWebDriver::class;
169+
$magentoWebDriverDoctor = '\\' . MagentoWebDriverDoctor::class;
141170

142-
// Check connectivity to Selenium through Codeception
143-
$this->output->writeln("\nChecking connectivity to Selenium Server ...");
144171
require_once realpath(self::CODECEPTION_AUTOLOAD_FILE);
145172

146173
$config = Configuration::config(realpath(self::MFTF_CODECEPTION_CONFIG_FILE));
147174
$settings = Configuration::suiteSettings(self::SUITE, $config);
175+
176+
// Enable MagentoWebDriverDoctor
177+
$settings['modules']['enabled'][] = $magentoWebDriverDoctor;
178+
$settings['modules']['config'][$magentoWebDriverDoctor] =
179+
$settings['modules']['config'][$magentoWebDriver];
180+
181+
// Disable MagentoWebDriver to avoid conflicts
182+
foreach ($settings['modules']['enabled'] as $index => $module) {
183+
if ($module == $magentoWebDriver) {
184+
unset($settings['modules']['enabled'][$index]);
185+
break;
186+
}
187+
}
188+
unset($settings['modules']['config'][$magentoWebDriver]);
189+
148190
$dispatcher = new EventDispatcher();
149191
$suiteManager = new SuiteManager($dispatcher, self::SUITE, $settings);
150192
try {
151193
$suiteManager->initialize();
152-
$this->output->writeln('Successful');
153-
$result = true;
194+
$this->context = ['Successful'];
154195
} catch (TestFrameworkException $e) {
155-
$this->output->writeln($e->getMessage());
196+
$this->context = $e->getContext();
156197
}
157-
return $result;
158198
}
159199
}

src/Magento/FunctionalTestingFramework/Exceptions/TestFrameworkException.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@
1313
*/
1414
class TestFrameworkException extends \Exception
1515
{
16+
/**
17+
* Exception context
18+
*
19+
* @var array
20+
*/
21+
protected $context;
22+
1623
/**
1724
* TestFrameworkException constructor.
1825
* @param string $message
@@ -27,6 +34,17 @@ public function __construct($message, $context = [])
2734
$context
2835
);
2936

37+
$this->context = $context;
3038
parent::__construct($message);
3139
}
40+
41+
/**
42+
* Return exception context
43+
*
44+
* @return array
45+
*/
46+
public function getContext()
47+
{
48+
return $this->context;
49+
}
3250
}

src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,6 @@ public function _initialize()
129129
$this->config = ConfigSanitizerUtil::sanitizeWebDriverConfig($this->config);
130130
parent::_initialize();
131131
$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-
}
137132
}
138133

139134
/**
@@ -834,32 +829,6 @@ public function makeScreenshot($name = null)
834829
AllureHelper::addAttachmentToCurrentStep($screenName, 'Screenshot');
835830
}
836831

837-
/**
838-
* Check connectivity to running selenium server
839-
*
840-
* @return void
841-
* @throws TestFrameworkException
842-
*/
843-
public function checkSeleniumServerReadiness()
844-
{
845-
try {
846-
$driver = RemoteWebDriver::create(
847-
$this->wdHost,
848-
$this->capabilities,
849-
$this->connectionTimeoutInMs,
850-
$this->requestTimeoutInMs,
851-
$this->httpProxy,
852-
$this->httpProxyPort
853-
);
854-
$driver->close();
855-
} catch (WebDriverCurlException $e) {
856-
throw new TestFrameworkException(
857-
"Can't connect to Webdriver at {$this->wdHost}.\n"
858-
. "Please make sure that Selenium Server is running."
859-
);
860-
}
861-
}
862-
863832
/**
864833
* Takes given $command and executes it against bin/magento executable. Returns stdout output from the command.
865834
*
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\FunctionalTestingFramework\Module;
8+
9+
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
10+
use Facebook\WebDriver\Remote\RemoteWebDriver;
11+
12+
/**
13+
* MagentoWebDriverDoctor module extends MagentoWebDriver module and is a light weighted module to diagnose webdriver
14+
* initialization and other setup issues. It uses in memory version of MagentoWebDriver's configuration file
15+
*/
16+
class MagentoWebDriverDoctor extends MagentoWebDriver
17+
{
18+
const MAGENTO_CLI_COMMAND = 'list';
19+
const EXCEPTION_TYPE_SELENIUM = 'selenium';
20+
const EXCEPTION_TYPE_MAGENTO_CLI = 'cli';
21+
22+
/**
23+
* Go through parent initialization routines and in addition diagnose potential environment issues
24+
*
25+
* @return void
26+
* @throws TestFrameworkException
27+
*/
28+
public function _initialize()
29+
{
30+
parent::_initialize();
31+
32+
$context = [];
33+
34+
try {
35+
$this->checkSeleniumServerReadiness();
36+
} catch (TestFrameworkException $e) {
37+
$context[self::EXCEPTION_TYPE_SELENIUM] = $e->getMessage();
38+
}
39+
40+
try {
41+
$this->checkMagentoCLI();
42+
} catch (TestFrameworkException $e) {
43+
$context[self::EXCEPTION_TYPE_MAGENTO_CLI] = $e->getMessage();
44+
}
45+
46+
if (!empty($context)) {
47+
throw new TestFrameworkException('MagentoWebDriverDoctor initialization failed', $context);
48+
}
49+
}
50+
51+
/**
52+
* Check connectivity to running selenium server
53+
*
54+
* @return void
55+
* @throws TestFrameworkException
56+
*/
57+
private function checkSeleniumServerReadiness()
58+
{
59+
try {
60+
$driver = RemoteWebDriver::create(
61+
$this->wdHost,
62+
$this->capabilities,
63+
$this->connectionTimeoutInMs,
64+
$this->requestTimeoutInMs,
65+
$this->httpProxy,
66+
$this->httpProxyPort
67+
);
68+
$driver->close();
69+
} catch (\Exception $e) {
70+
throw new TestFrameworkException(
71+
"Can't connect to Webdriver at {$this->wdHost}.\n"
72+
. "Please make sure that Selenium Server is running."
73+
);
74+
}
75+
}
76+
77+
/**
78+
* Check Magento CLI setup
79+
*
80+
* @return void
81+
* @throws TestFrameworkException
82+
*/
83+
private function checkMagentoCLI()
84+
{
85+
parent::magentoCLI(self::MAGENTO_CLI_COMMAND);
86+
}
87+
}

0 commit comments

Comments
 (0)