From 7ac812bed2cfe6f4f2570a4c818e1e3b0f4db5f8 Mon Sep 17 00:00:00 2001 From: Ji Lu Date: Wed, 30 Oct 2019 15:06:09 -0500 Subject: [PATCH 1/8] MQE-1257: MFTF Troubleshoot command --- dev/tests/functional/standalone_bootstrap.php | 8 +- .../Config/MftfApplicationConfig.php | 3 +- .../Console/CommandList.php | 27 +-- .../Console/TroubleShootCommand.php | 158 ++++++++++++++++++ .../Module/MagentoWebDriver.php | 33 ++++ .../Util/ModuleResolver.php | 2 +- .../FunctionalTestingFramework/_bootstrap.php | 8 +- 7 files changed, 218 insertions(+), 21 deletions(-) create mode 100644 src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php diff --git a/dev/tests/functional/standalone_bootstrap.php b/dev/tests/functional/standalone_bootstrap.php index 763062d04..de6ef394d 100755 --- a/dev/tests/functional/standalone_bootstrap.php +++ b/dev/tests/functional/standalone_bootstrap.php @@ -15,10 +15,12 @@ require_once realpath(PROJECT_ROOT . '/vendor/autoload.php'); +$envFilePath = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR; +defined('ENV_FILE_PATH') || define('ENV_FILE_PATH', $envFilePath); + //Load constants from .env file -$envFilePath = dirname(dirname(__DIR__)); -if (file_exists($envFilePath . DIRECTORY_SEPARATOR . '.env')) { - $env = new \Dotenv\Loader($envFilePath . DIRECTORY_SEPARATOR . '.env'); +if (file_exists(ENV_FILE_PATH . '.env')) { + $env = new \Dotenv\Loader(ENV_FILE_PATH . '.env'); $env->load(); foreach ($_ENV as $key => $var) { diff --git a/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php b/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php index 80db27de0..f429110d7 100644 --- a/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php +++ b/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php @@ -15,7 +15,8 @@ class MftfApplicationConfig const GENERATION_PHASE = "generation"; const EXECUTION_PHASE = "execution"; const UNIT_TEST_PHASE = "testing"; - const MFTF_PHASES = [self::GENERATION_PHASE, self::EXECUTION_PHASE, self::UNIT_TEST_PHASE]; + const DIAGNOSTIC_PHASE = "diagnostic"; + const MFTF_PHASES = [self::GENERATION_PHASE, self::EXECUTION_PHASE, self::UNIT_TEST_PHASE, self::DIAGNOSTIC_PHASE]; /** * Mftf debug levels diff --git a/src/Magento/FunctionalTestingFramework/Console/CommandList.php b/src/Magento/FunctionalTestingFramework/Console/CommandList.php index 34d221840..be62227ac 100644 --- a/src/Magento/FunctionalTestingFramework/Console/CommandList.php +++ b/src/Magento/FunctionalTestingFramework/Console/CommandList.php @@ -29,19 +29,20 @@ class CommandList implements CommandListInterface public function __construct(array $commands = []) { $this->commands = [ - 'build:project' => new BuildProjectCommand(), - 'reset' => new CleanProjectCommand(), - 'generate:urn-catalog' => new GenerateDevUrnCommand(), - 'generate:suite' => new GenerateSuiteCommand(), - 'generate:tests' => new GenerateTestsCommand(), - 'run:test' => new RunTestCommand(), - 'run:group' => new RunTestGroupCommand(), - 'run:failed' => new RunTestFailedCommand(), - 'run:manifest' => new RunManifestCommand(), - 'setup:env' => new SetupEnvCommand(), - 'upgrade:tests' => new UpgradeTestsCommand(), - 'generate:docs' => new GenerateDocsCommand(), - 'static-checks' => new StaticChecksCommand() + 'build:project' => new BuildProjectCommand(), + 'generate:docs' => new GenerateDocsCommand(), + 'generate:suite' => new GenerateSuiteCommand(), + 'generate:tests' => new GenerateTestsCommand(), + 'generate:urn-catalog' => new GenerateDevUrnCommand(), + 'reset' => new CleanProjectCommand(), + 'run:failed' => new RunTestFailedCommand(), + 'run:group' => new RunTestGroupCommand(), + 'run:manifest' => new RunManifestCommand(), + 'run:test' => new RunTestCommand(), + 'setup:env' => new SetupEnvCommand(), + 'static-checks' => new StaticChecksCommand(), + 'troubleshoot' => new TroubleShootCommand(), + 'upgrade:tests' => new UpgradeTestsCommand(), ] + $commands; } diff --git a/src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php b/src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php new file mode 100644 index 000000000..124473bcd --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php @@ -0,0 +1,158 @@ +setName('troubleshoot') + ->setDescription( + 'This command checks environment readiness for generating and running MFTF tests.' + ); + } + + /** + * Executes the current command. + * + * @param InputInterface $input + * @param OutputInterface $output + * @return void + * @throws TestFrameworkException + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $cmdStatus = true; + + // Config application + $verbose = $output->isVerbose(); + $this->output = $output; + MftfApplicationConfig::create( + false, + MftfApplicationConfig::DIAGNOSTIC_PHASE, + $verbose, + MftfApplicationConfig::LEVEL_DEVELOPER, + false + ); + + // Check required PHP extensions + foreach (self::REQUIRED_PHP_EXTS as $ext) { + $status = $this->checkPhpExtIsAvailable($ext); + $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; + } + + // Check authentication to Magento Admin + $status = $this->checkAuthenticationToMagentoAdmin(); + $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; + + // Check connectivity and authentication to Magento Admin + $status = $this->checkConnectivityToSeleniumServer(); + $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; + + if ($cmdStatus) { + exit(0); + } else { + exit(1); + } + } + + /** + * Check php extention is installed and available + * + * @param string $ext + * @return boolean + */ + private function checkPhpExtIsAvailable($ext) + { + $result = false; + $this->output->writeln("\nChecking PHP extenstion \"{$ext}\" ..."); + if (extension_loaded(strtolower($ext))) { + $this->output->writeln('Successful'); + $result = true; + } else { + $this->output->writeln( + "MFTF requires \"{$ext}\" extension installed to make tests run\n" + . "Please make sure that the PHP you run has \"{$ext}\" installed and enabled." + ); + } + return $result; + } + + /** + * Check authentication to Magento Admin + * + * @return boolean + */ + private function checkAuthenticationToMagentoAdmin() + { + $result = false; + try { + $this->output->writeln("\nChecking authentication to Magento Admin ..."); + ModuleResolver::getInstance()->getAdminToken(); + $this->output->writeln('Successful'); + $result = true; + } catch (TestFrameworkException $e) { + $this->output->writeln($e->getMessage()); + } + return $result; + } + + /** + * Check Connectivity to Selenium Server + * + * @return boolean + */ + private function checkConnectivityToSeleniumServer() + { + $result = false; + + // Check connectivity to Selenium through Codeception + $this->output->writeln("\nChecking connectivity to Selenium Server ..."); + require_once realpath(self::CODECEPTION_AUTOLOAD_FILE); + + $config = Configuration::config(realpath(self::MFTF_CODECEPTION_CONFIG_FILE)); + $settings = Configuration::suiteSettings(self::SUITE, $config); + $dispatcher = new EventDispatcher(); + $suiteManager = new SuiteManager($dispatcher, self::SUITE, $settings); + try { + $suiteManager->initialize(); + $this->output->writeln('Successful'); + $result = true; + } catch (TestFrameworkException $e) { + $this->output->writeln($e->getMessage()); + } + return $result; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php index 17a868efd..248e16e44 100644 --- a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php @@ -23,6 +23,9 @@ use Symfony\Component\Process\Process; use Yandex\Allure\Adapter\Support\AttachmentSupport; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; +use Facebook\WebDriver\Remote\RemoteWebDriver; +use Facebook\WebDriver\Exception\WebDriverCurlException; /** * MagentoWebDriver module provides common Magento web actions through Selenium WebDriver. @@ -126,6 +129,11 @@ public function _initialize() $this->config = ConfigSanitizerUtil::sanitizeWebDriverConfig($this->config); parent::_initialize(); $this->cleanJsError(); + + // Check Selenium Server readiness if it's in diagnostic phase + if (MftfApplicationConfig::getConfig()->getPhase() === MftfApplicationConfig::DIAGNOSTIC_PHASE) { + $this->checkSeleniumServerReadiness(); + } } /** @@ -826,6 +834,31 @@ public function makeScreenshot($name = null) AllureHelper::addAttachmentToCurrentStep($screenName, 'Screenshot'); } + /** + * Check connectivity to running selenium server + * + * @return void + * @throws TestFrameworkException + */ + public function checkSeleniumServerReadiness() + { + try { + RemoteWebDriver::create( + $this->wdHost, + $this->capabilities, + $this->connectionTimeoutInMs, + $this->requestTimeoutInMs, + $this->httpProxy, + $this->httpProxyPort + ); + } catch (WebDriverCurlException $e) { + throw new TestFrameworkException( + "Can't connect to Webdriver at {$this->wdHost}.\n" + . "Please make sure that Selenium Server is running." + ); + } + } + /** * Takes given $command and executes it against bin/magento executable. Returns stdout output from the command. * diff --git a/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php b/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php index d776603d1..c9c050878 100644 --- a/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php +++ b/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php @@ -703,7 +703,7 @@ private function printMagentoVersionInfo() * * @return string|boolean */ - protected function getAdminToken() + public function getAdminToken() { $login = $_ENV['MAGENTO_ADMIN_USERNAME'] ?? null; $password = $_ENV['MAGENTO_ADMIN_PASSWORD'] ?? null; diff --git a/src/Magento/FunctionalTestingFramework/_bootstrap.php b/src/Magento/FunctionalTestingFramework/_bootstrap.php index 34807d2b9..dd7cfd37d 100644 --- a/src/Magento/FunctionalTestingFramework/_bootstrap.php +++ b/src/Magento/FunctionalTestingFramework/_bootstrap.php @@ -15,11 +15,13 @@ return; } defined('PROJECT_ROOT') || define('PROJECT_ROOT', $projectRootPath); -$envFilepath = realpath($projectRootPath . '/dev/tests/acceptance/'); +$envFilePath = realpath($projectRootPath . '/dev/tests/acceptance/'); +defined('ENV_FILE_PATH') || define('ENV_FILE_PATH', $envFilePath); -if (file_exists($envFilepath . DIRECTORY_SEPARATOR . '.env')) { - $env = new \Dotenv\Loader($envFilepath . DIRECTORY_SEPARATOR . '.env'); +//Load constants from .env file +if (file_exists(ENV_FILE_PATH . '.env')) { + $env = new \Dotenv\Loader(ENV_FILE_PATH . '.env'); $env->load(); if (array_key_exists('TESTS_MODULE_PATH', $_ENV) xor array_key_exists('TESTS_BP', $_ENV)) { From 7bdcafd91775c627377482a41bede5f9e80b9e9e Mon Sep 17 00:00:00 2001 From: Ji Lu Date: Wed, 30 Oct 2019 15:34:47 -0500 Subject: [PATCH 2/8] MQE-1257: MFTF Troubleshoot command --- .../Console/TroubleShootCommand.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php b/src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php index 124473bcd..3dc9cb288 100644 --- a/src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php @@ -49,8 +49,9 @@ protected function configure() * * @param InputInterface $input * @param OutputInterface $output - * @return void + * @return integer * @throws TestFrameworkException + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -82,9 +83,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; if ($cmdStatus) { - exit(0); + return 0; } else { - exit(1); + return 1; } } From 4fdf441f93b476dbeeb72a6cb032f50ee50bf06d Mon Sep 17 00:00:00 2001 From: Ji Lu Date: Wed, 30 Oct 2019 16:09:03 -0500 Subject: [PATCH 3/8] MQE-1257: MFTF Troubleshoot command --- .../FunctionalTestingFramework/Module/MagentoWebDriver.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php index 248e16e44..2b41af99e 100644 --- a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php @@ -843,7 +843,7 @@ public function makeScreenshot($name = null) public function checkSeleniumServerReadiness() { try { - RemoteWebDriver::create( + $driver = RemoteWebDriver::create( $this->wdHost, $this->capabilities, $this->connectionTimeoutInMs, @@ -851,6 +851,7 @@ public function checkSeleniumServerReadiness() $this->httpProxy, $this->httpProxyPort ); + $driver->close(); } catch (WebDriverCurlException $e) { throw new TestFrameworkException( "Can't connect to Webdriver at {$this->wdHost}.\n" From f1299b1b03e2bfe7eb1a6382985b91fb3edba6de Mon Sep 17 00:00:00 2001 From: Ji Lu Date: Fri, 8 Nov 2019 16:41:32 -0600 Subject: [PATCH 4/8] MQE-1257: MFTF doctor command --- .../Config/MftfApplicationConfig.php | 3 +- .../Console/CommandList.php | 2 +- ...ubleShootCommand.php => DoctorCommand.php} | 122 ++++++++++++------ .../Exceptions/TestFrameworkException.php | 18 +++ .../Module/MagentoWebDriver.php | 31 ----- .../Module/MagentoWebDriverDoctor.php | 87 +++++++++++++ 6 files changed, 188 insertions(+), 75 deletions(-) rename src/Magento/FunctionalTestingFramework/Console/{TroubleShootCommand.php => DoctorCommand.php} (56%) create mode 100644 src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php diff --git a/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php b/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php index f429110d7..80db27de0 100644 --- a/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php +++ b/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php @@ -15,8 +15,7 @@ class MftfApplicationConfig const GENERATION_PHASE = "generation"; const EXECUTION_PHASE = "execution"; const UNIT_TEST_PHASE = "testing"; - const DIAGNOSTIC_PHASE = "diagnostic"; - const MFTF_PHASES = [self::GENERATION_PHASE, self::EXECUTION_PHASE, self::UNIT_TEST_PHASE, self::DIAGNOSTIC_PHASE]; + const MFTF_PHASES = [self::GENERATION_PHASE, self::EXECUTION_PHASE, self::UNIT_TEST_PHASE]; /** * Mftf debug levels diff --git a/src/Magento/FunctionalTestingFramework/Console/CommandList.php b/src/Magento/FunctionalTestingFramework/Console/CommandList.php index be62227ac..bf9cbd58e 100644 --- a/src/Magento/FunctionalTestingFramework/Console/CommandList.php +++ b/src/Magento/FunctionalTestingFramework/Console/CommandList.php @@ -30,6 +30,7 @@ public function __construct(array $commands = []) { $this->commands = [ 'build:project' => new BuildProjectCommand(), + 'doctor' => new DoctorCommand(), 'generate:docs' => new GenerateDocsCommand(), 'generate:suite' => new GenerateSuiteCommand(), 'generate:tests' => new GenerateTestsCommand(), @@ -41,7 +42,6 @@ public function __construct(array $commands = []) 'run:test' => new RunTestCommand(), 'setup:env' => new SetupEnvCommand(), 'static-checks' => new StaticChecksCommand(), - 'troubleshoot' => new TroubleShootCommand(), 'upgrade:tests' => new UpgradeTestsCommand(), ] + $commands; } diff --git a/src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php b/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php similarity index 56% rename from src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php rename to src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php index 3dc9cb288..469d4ac47 100644 --- a/src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php @@ -16,13 +16,14 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Magento\FunctionalTestingFramework\Util\ModuleResolver; +use Magento\FunctionalTestingFramework\Module\MagentoWebDriver; +use Magento\FunctionalTestingFramework\Module\MagentoWebDriverDoctor; -class TroubleShootCommand extends Command +class DoctorCommand extends Command { const CODECEPTION_AUTOLOAD_FILE = PROJECT_ROOT . '/vendor/codeception/codeception/autoload.php'; const MFTF_CODECEPTION_CONFIG_FILE = ENV_FILE_PATH . 'codeception.yml'; const SUITE = 'functional'; - const REQUIRED_PHP_EXTS = ['CURL', 'mbstring', 'bcmath', 'zip', 'dom', 'gd', 'intl']; /** * Command Output @@ -31,6 +32,13 @@ class TroubleShootCommand extends Command */ private $output; + /** + * Exception Context + * + * @var array + */ + private $context = []; + /** * Configures the current command. * @@ -38,7 +46,7 @@ class TroubleShootCommand extends Command */ protected function configure() { - $this->setName('troubleshoot') + $this->setName('doctor') ->setDescription( 'This command checks environment readiness for generating and running MFTF tests.' ); @@ -62,24 +70,22 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->output = $output; MftfApplicationConfig::create( false, - MftfApplicationConfig::DIAGNOSTIC_PHASE, + MftfApplicationConfig::GENERATION_PHASE, $verbose, MftfApplicationConfig::LEVEL_DEVELOPER, false ); - // Check required PHP extensions - foreach (self::REQUIRED_PHP_EXTS as $ext) { - $status = $this->checkPhpExtIsAvailable($ext); - $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; - } - // Check authentication to Magento Admin $status = $this->checkAuthenticationToMagentoAdmin(); $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; - // Check connectivity and authentication to Magento Admin - $status = $this->checkConnectivityToSeleniumServer(); + // Check connection to Selenium + $status = $this->checkConnectionToSeleniumServer(); + $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; + + // Check access to Magento CLI + $status = $this->checkAccessToMagentoCLI(); $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; if ($cmdStatus) { @@ -90,70 +96,104 @@ protected function execute(InputInterface $input, OutputInterface $output) } /** - * Check php extention is installed and available + * Check authentication to Magento Admin * - * @param string $ext * @return boolean */ - private function checkPhpExtIsAvailable($ext) + private function checkAuthenticationToMagentoAdmin() { $result = false; - $this->output->writeln("\nChecking PHP extenstion \"{$ext}\" ..."); - if (extension_loaded(strtolower($ext))) { + try { + $this->output->writeln("\nChecking authentication to Magento Admin ..."); + ModuleResolver::getInstance()->getAdminToken(); $this->output->writeln('Successful'); $result = true; - } else { - $this->output->writeln( - "MFTF requires \"{$ext}\" extension installed to make tests run\n" - . "Please make sure that the PHP you run has \"{$ext}\" installed and enabled." - ); + } catch (TestFrameworkException $e) { + $this->output->writeln($e->getMessage()); } return $result; } /** - * Check authentication to Magento Admin + * Check Connection to Selenium Server * * @return boolean */ - private function checkAuthenticationToMagentoAdmin() + private function checkConnectionToSeleniumServer() { - $result = false; - try { - $this->output->writeln("\nChecking authentication to Magento Admin ..."); - ModuleResolver::getInstance()->getAdminToken(); + // Check connection to Selenium through Codeception + $this->output->writeln("\nChecking connection to Selenium Server ..."); + $this->runMagentoWebDriverDoctor(); + + if (isset($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_SELENIUM])) { + $this->output->write($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_SELENIUM] . "\n"); + return false; + } else { $this->output->writeln('Successful'); - $result = true; - } catch (TestFrameworkException $e) { - $this->output->writeln($e->getMessage()); + return true; } - return $result; } /** - * Check Connectivity to Selenium Server + * Check access to Magento CLI setup * * @return boolean */ - private function checkConnectivityToSeleniumServer() + private function checkAccessToMagentoCLI() { - $result = false; + // Check Magento CLI setup + $this->output->writeln("\nChecking access to Magento CLI ..."); + $this->runMagentoWebDriverDoctor(); + + if (isset($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_MAGENTO_CLI])) { + $this->output->write($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_MAGENTO_CLI] . "\n"); + return false; + } else { + $this->output->writeln('Successful'); + return true; + } + } + + /** + * Run diagnose through MagentoWebDriverDoctor + * + * @return void + */ + private function runMagentoWebDriverDoctor() + { + if (!empty($this->context)) { + return; + } + + $magentoWebDriver = '\\' . MagentoWebDriver::class; + $magentoWebDriverDoctor = '\\' . MagentoWebDriverDoctor::class; - // Check connectivity to Selenium through Codeception - $this->output->writeln("\nChecking connectivity to Selenium Server ..."); require_once realpath(self::CODECEPTION_AUTOLOAD_FILE); $config = Configuration::config(realpath(self::MFTF_CODECEPTION_CONFIG_FILE)); $settings = Configuration::suiteSettings(self::SUITE, $config); + + // Enable MagentoWebDriverDoctor + $settings['modules']['enabled'][] = $magentoWebDriverDoctor; + $settings['modules']['config'][$magentoWebDriverDoctor] = + $settings['modules']['config'][$magentoWebDriver]; + + // Disable MagentoWebDriver to avoid conflicts + foreach ($settings['modules']['enabled'] as $index => $module) { + if ($module == $magentoWebDriver) { + unset($settings['modules']['enabled'][$index]); + break; + } + } + unset($settings['modules']['config'][$magentoWebDriver]); + $dispatcher = new EventDispatcher(); $suiteManager = new SuiteManager($dispatcher, self::SUITE, $settings); try { $suiteManager->initialize(); - $this->output->writeln('Successful'); - $result = true; + $this->context = ['Successful']; } catch (TestFrameworkException $e) { - $this->output->writeln($e->getMessage()); + $this->context = $e->getContext(); } - return $result; } } diff --git a/src/Magento/FunctionalTestingFramework/Exceptions/TestFrameworkException.php b/src/Magento/FunctionalTestingFramework/Exceptions/TestFrameworkException.php index 5e9e594c0..a82eddef0 100644 --- a/src/Magento/FunctionalTestingFramework/Exceptions/TestFrameworkException.php +++ b/src/Magento/FunctionalTestingFramework/Exceptions/TestFrameworkException.php @@ -13,6 +13,13 @@ */ class TestFrameworkException extends \Exception { + /** + * Exception context + * + * @var array + */ + protected $context; + /** * TestFrameworkException constructor. * @param string $message @@ -27,6 +34,17 @@ public function __construct($message, $context = []) $context ); + $this->context = $context; parent::__construct($message); } + + /** + * Return exception context + * + * @return array + */ + public function getContext() + { + return $this->context; + } } diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php index 2b41af99e..215438420 100644 --- a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php @@ -129,11 +129,6 @@ public function _initialize() $this->config = ConfigSanitizerUtil::sanitizeWebDriverConfig($this->config); parent::_initialize(); $this->cleanJsError(); - - // Check Selenium Server readiness if it's in diagnostic phase - if (MftfApplicationConfig::getConfig()->getPhase() === MftfApplicationConfig::DIAGNOSTIC_PHASE) { - $this->checkSeleniumServerReadiness(); - } } /** @@ -834,32 +829,6 @@ public function makeScreenshot($name = null) AllureHelper::addAttachmentToCurrentStep($screenName, 'Screenshot'); } - /** - * Check connectivity to running selenium server - * - * @return void - * @throws TestFrameworkException - */ - public function checkSeleniumServerReadiness() - { - try { - $driver = RemoteWebDriver::create( - $this->wdHost, - $this->capabilities, - $this->connectionTimeoutInMs, - $this->requestTimeoutInMs, - $this->httpProxy, - $this->httpProxyPort - ); - $driver->close(); - } catch (WebDriverCurlException $e) { - throw new TestFrameworkException( - "Can't connect to Webdriver at {$this->wdHost}.\n" - . "Please make sure that Selenium Server is running." - ); - } - } - /** * Takes given $command and executes it against bin/magento executable. Returns stdout output from the command. * diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php new file mode 100644 index 000000000..3acde4a42 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php @@ -0,0 +1,87 @@ +checkSeleniumServerReadiness(); + } catch (TestFrameworkException $e) { + $context[self::EXCEPTION_TYPE_SELENIUM] = $e->getMessage(); + } + + try { + $this->checkMagentoCLI(); + } catch (TestFrameworkException $e) { + $context[self::EXCEPTION_TYPE_MAGENTO_CLI] = $e->getMessage(); + } + + if (!empty($context)) { + throw new TestFrameworkException('MagentoWebDriverDoctor initialization failed', $context); + } + } + + /** + * Check connectivity to running selenium server + * + * @return void + * @throws TestFrameworkException + */ + private function checkSeleniumServerReadiness() + { + try { + $driver = RemoteWebDriver::create( + $this->wdHost, + $this->capabilities, + $this->connectionTimeoutInMs, + $this->requestTimeoutInMs, + $this->httpProxy, + $this->httpProxyPort + ); + $driver->close(); + } catch (\Exception $e) { + throw new TestFrameworkException( + "Can't connect to Webdriver at {$this->wdHost}.\n" + . "Please make sure that Selenium Server is running." + ); + } + } + + /** + * Check Magento CLI setup + * + * @return void + * @throws TestFrameworkException + */ + private function checkMagentoCLI() + { + parent::magentoCLI(self::MAGENTO_CLI_COMMAND); + } +} From 25c5706cc2df7384de31b6804fc5d76b120a347c Mon Sep 17 00:00:00 2001 From: Ji Lu Date: Thu, 14 Nov 2019 15:46:24 -0600 Subject: [PATCH 5/8] MQE-1257: MFTF doctor command --- docs/commands/mftf.md | 14 +++ .../Console/DoctorCommand.php | 64 ++++++----- .../Module/MagentoWebDriverDoctor.php | 108 +++++++++++++++--- 3 files changed, 139 insertions(+), 47 deletions(-) diff --git a/docs/commands/mftf.md b/docs/commands/mftf.md index 58be6501e..5e9895958 100644 --- a/docs/commands/mftf.md +++ b/docs/commands/mftf.md @@ -109,6 +109,20 @@ You can include options to set configuration parameter values for your environme vendor/bin/mftf build:project --MAGENTO_BASE_URL=http://magento.local/ --MAGENTO_BACKEND_NAME=admin214365 ``` +### `doctor` + +#### Description + +Diagnose MFTF configuration and setup + +#### Usage + +```bash +vendor/bin/mftf doctor +``` + +#### Options + ### `generate:tests` #### Description diff --git a/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php b/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php index 469d4ac47..2caa47437 100644 --- a/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php @@ -67,6 +67,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // Config application $verbose = $output->isVerbose(); + $this->input = $input; $this->output = $output; MftfApplicationConfig::create( false, @@ -81,11 +82,31 @@ protected function execute(InputInterface $input, OutputInterface $output) $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; // Check connection to Selenium - $status = $this->checkConnectionToSeleniumServer(); + $status = $this->checkContextOnStep( + MagentoWebDriverDoctor::EXCEPTION_CONTEXT_SELENIUM, + 'Connecting to Selenium Server' + ); + $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; + + // Check opening Magento Admin in web browser + $status = $this->checkContextOnStep( + MagentoWebDriverDoctor::EXCEPTION_CONTEXT_ADMIN, + 'Loading Admin page' + ); + $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; + + // Check opening Magento Storefront in web browser + $status = $this->checkContextOnStep( + MagentoWebDriverDoctor::EXCEPTION_CONTEXT_STOREFRONT, + 'Loading Storefront page' + ); $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; // Check access to Magento CLI - $status = $this->checkAccessToMagentoCLI(); + $status = $this->checkContextOnStep( + MagentoWebDriverDoctor::EXCEPTION_CONTEXT_CLI, + 'Running Magento CLI' + ); $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; if ($cmdStatus) { @@ -96,7 +117,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } /** - * Check authentication to Magento Admin + * Check admin account authentication * * @return boolean */ @@ -104,7 +125,7 @@ private function checkAuthenticationToMagentoAdmin() { $result = false; try { - $this->output->writeln("\nChecking authentication to Magento Admin ..."); + $this->output->writeln("\nAuthenticating admin account by API ..."); ModuleResolver::getInstance()->getAdminToken(); $this->output->writeln('Successful'); $result = true; @@ -115,38 +136,20 @@ private function checkAuthenticationToMagentoAdmin() } /** - * Check Connection to Selenium Server - * - * @return boolean - */ - private function checkConnectionToSeleniumServer() - { - // Check connection to Selenium through Codeception - $this->output->writeln("\nChecking connection to Selenium Server ..."); - $this->runMagentoWebDriverDoctor(); - - if (isset($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_SELENIUM])) { - $this->output->write($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_SELENIUM] . "\n"); - return false; - } else { - $this->output->writeln('Successful'); - return true; - } - } - - /** - * Check access to Magento CLI setup + * Check exception context after runMagentoWebDriverDoctor * + * @param string $exceptionType + * @param string $message * @return boolean + * @throws TestFrameworkException */ - private function checkAccessToMagentoCLI() + private function checkContextOnStep($exceptionType, $message) { - // Check Magento CLI setup - $this->output->writeln("\nChecking access to Magento CLI ..."); + $this->output->writeln("\n$message ..."); $this->runMagentoWebDriverDoctor(); - if (isset($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_MAGENTO_CLI])) { - $this->output->write($this->context[MagentoWebDriverDoctor::EXCEPTION_TYPE_MAGENTO_CLI] . "\n"); + if (isset($this->context[$exceptionType])) { + $this->output->write($this->context[$exceptionType] . "\n"); return false; } else { $this->output->writeln('Successful'); @@ -158,6 +161,7 @@ private function checkAccessToMagentoCLI() * Run diagnose through MagentoWebDriverDoctor * * @return void + * @throws TestFrameworkException */ private function runMagentoWebDriverDoctor() { diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php index 3acde4a42..35fa37f03 100644 --- a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php @@ -11,13 +11,22 @@ /** * MagentoWebDriverDoctor module extends MagentoWebDriver module and is a light weighted module to diagnose webdriver - * initialization and other setup issues. It uses in memory version of MagentoWebDriver's configuration file + * initialization and other setup issues. It uses in memory version of MagentoWebDriver's configuration file. */ class MagentoWebDriverDoctor extends MagentoWebDriver { const MAGENTO_CLI_COMMAND = 'list'; - const EXCEPTION_TYPE_SELENIUM = 'selenium'; - const EXCEPTION_TYPE_MAGENTO_CLI = 'cli'; + const EXCEPTION_CONTEXT_SELENIUM = 'selenium'; + const EXCEPTION_CONTEXT_ADMIN = 'admin'; + const EXCEPTION_CONTEXT_STOREFRONT = 'store'; + const EXCEPTION_CONTEXT_CLI = 'cli'; + + /** + * Remote Web Driver + * + * @var RemoteWebDriver + */ + private $remoteWebDriver = null; /** * Go through parent initialization routines and in addition diagnose potential environment issues @@ -32,32 +41,52 @@ public function _initialize() $context = []; try { - $this->checkSeleniumServerReadiness(); + $this->connectToSeleniumServer(); } catch (TestFrameworkException $e) { - $context[self::EXCEPTION_TYPE_SELENIUM] = $e->getMessage(); + $context[self::EXCEPTION_CONTEXT_SELENIUM] = $e->getMessage(); } try { - $this->checkMagentoCLI(); - } catch (TestFrameworkException $e) { - $context[self::EXCEPTION_TYPE_MAGENTO_CLI] = $e->getMessage(); + $adminUrl = rtrim(getenv('MAGENTO_BACKEND_BASE_URL'), '/') + ?: rtrim(getenv('MAGENTO_BASE_URL'), '/') + . '/' . getenv('MAGENTO_BACKEND_NAME') . '/admin'; + $this->loadPageAtUrl($adminUrl); + } catch (\Exception $e) { + $context[self::EXCEPTION_CONTEXT_ADMIN] = $e->getMessage(); + } + + try { + $storeUrl = getenv('MAGENTO_BASE_URL'); + $this->loadPageAtUrl($storeUrl); + } catch (\Exception $e) { + $context[self::EXCEPTION_CONTEXT_STOREFRONT] = $e->getMessage(); + } + + try { + $this->runMagentoCLI(); + } catch (\Exception $e) { + $context[self::EXCEPTION_CONTEXT_CLI] = $e->getMessage(); + } + + if (null !== $this->remoteWebDriver) { + $this->remoteWebDriver->close(); } if (!empty($context)) { - throw new TestFrameworkException('MagentoWebDriverDoctor initialization failed', $context); + throw new TestFrameworkException('Exception occurred in MagentoWebDriverDoctor', $context); } } /** - * Check connectivity to running selenium server + * Check connecting to running selenium server * * @return void * @throws TestFrameworkException */ - private function checkSeleniumServerReadiness() + private function connectToSeleniumServer() { try { - $driver = RemoteWebDriver::create( + $this->remoteWebDriver = RemoteWebDriver::create( $this->wdHost, $this->capabilities, $this->connectionTimeoutInMs, @@ -65,23 +94,68 @@ private function checkSeleniumServerReadiness() $this->httpProxy, $this->httpProxyPort ); - $driver->close(); } catch (\Exception $e) { throw new TestFrameworkException( - "Can't connect to Webdriver at {$this->wdHost}.\n" + "Failed to connect Selenium WebDriver at: {$this->wdHost}.\n" . "Please make sure that Selenium Server is running." ); } } /** - * Check Magento CLI setup + * Validate loading a web page at url in the browser controlled by selenium + * + * @param string $url + * @return void + * @throws TestFrameworkException + */ + private function loadPageAtUrl($url) + { + try { + // Open the web page at url first + $this->remoteWebDriver->get($url); + + // Execute Javascript to retrieve HTTP response code + $script = '' + . 'var xhr = new XMLHttpRequest();' + . "xhr.open('GET', '" . $url . "', false);" + . 'xhr.send(null); ' + . 'return xhr.status'; + $status = $this->remoteWebDriver->executeScript($script); + + if ($status === 200) { + return; + } + } catch (\Exception $e) { + } + + throw new TestFrameworkException( + "Failed to load page at url: $url\n" + . "Please check network connection for the browser running Selenium." + ); + } + + /** + * Check running Magento CLI command * * @return void * @throws TestFrameworkException */ - private function checkMagentoCLI() + private function runMagentoCLI() { - parent::magentoCLI(self::MAGENTO_CLI_COMMAND); + try { + $regex = '~^.*(?Magento CLI).*[\r\n]+(?Usage:).*~'; + $output = parent::magentoCLI(self::MAGENTO_CLI_COMMAND); + preg_match($regex, $output, $matches); + + if (isset($matches['name']) && isset($matches['usage'])) { + return; + } + } catch (\Exception $e) { + throw new TestFrameworkException( + "Failed to run Magento CLI command\n" + . "Please reference Magento DevDoc to setup command.php and .htaccess files." + ); + } } } From 4908777736d79ab58d04c72035957b38469fb3d6 Mon Sep 17 00:00:00 2001 From: Ji Lu Date: Fri, 15 Nov 2019 15:45:33 -0600 Subject: [PATCH 6/8] MQE-1257: MFTF doctor command - config color for console output --- .../Console/DoctorCommand.php | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php b/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php index 2caa47437..d75004fc2 100644 --- a/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php @@ -24,6 +24,10 @@ class DoctorCommand extends Command const CODECEPTION_AUTOLOAD_FILE = PROJECT_ROOT . '/vendor/codeception/codeception/autoload.php'; const MFTF_CODECEPTION_CONFIG_FILE = ENV_FILE_PATH . 'codeception.yml'; const SUITE = 'functional'; + const COLOR_LIGHT_GREEN = "\e[1;32m"; + const COLOR_LIGHT_RED = "\e[1;31m"; + const COLOR_LIGHT_DEFAULT = "\e[1;39m"; + const COLOR_RESTORE = "\e[0m"; /** * Command Output @@ -60,6 +64,7 @@ protected function configure() * @return integer * @throws TestFrameworkException * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -109,11 +114,7 @@ protected function execute(InputInterface $input, OutputInterface $output) ); $cmdStatus = $cmdStatus && !$status ? false : $cmdStatus; - if ($cmdStatus) { - return 0; - } else { - return 1; - } + return $cmdStatus ? 0 : 1; } /** @@ -125,12 +126,14 @@ private function checkAuthenticationToMagentoAdmin() { $result = false; try { - $this->output->writeln("\nAuthenticating admin account by API ..."); + $this->output->writeln( + "\n" . self::COLOR_LIGHT_DEFAULT . "Authenticating admin account by API ..." . self::COLOR_RESTORE + ); ModuleResolver::getInstance()->getAdminToken(); - $this->output->writeln('Successful'); + $this->output->writeln(self::COLOR_LIGHT_GREEN . 'Successful' . self::COLOR_RESTORE); $result = true; } catch (TestFrameworkException $e) { - $this->output->writeln($e->getMessage()); + $this->output->writeln(self::COLOR_LIGHT_RED . $e->getMessage() . self::COLOR_RESTORE); } return $result; } @@ -145,14 +148,14 @@ private function checkAuthenticationToMagentoAdmin() */ private function checkContextOnStep($exceptionType, $message) { - $this->output->writeln("\n$message ..."); + $this->output->writeln("\n" . self::COLOR_LIGHT_DEFAULT. $message . self::COLOR_RESTORE); $this->runMagentoWebDriverDoctor(); if (isset($this->context[$exceptionType])) { - $this->output->write($this->context[$exceptionType] . "\n"); + $this->output->writeln(self::COLOR_LIGHT_RED . $this->context[$exceptionType] . self::COLOR_RESTORE); return false; } else { - $this->output->writeln('Successful'); + $this->output->writeln(self::COLOR_LIGHT_GREEN . 'Successful' . self::COLOR_RESTORE); return true; } } From bea39a96e4822f8259633cd63e830b0febb552b9 Mon Sep 17 00:00:00 2001 From: Ji Lu Date: Tue, 19 Nov 2019 09:25:11 -0600 Subject: [PATCH 7/8] MQE-1257: MFTF doctor command --- docs/commands/mftf.md | 6 ++- .../Console/DoctorCommand.php | 34 ++++++++-------- .../Module/MagentoWebDriverDoctor.php | 40 +++++++++++-------- .../FunctionalTestingFramework/_bootstrap.php | 2 +- 4 files changed, 45 insertions(+), 37 deletions(-) diff --git a/docs/commands/mftf.md b/docs/commands/mftf.md index 5e9895958..a71b8a02c 100644 --- a/docs/commands/mftf.md +++ b/docs/commands/mftf.md @@ -113,7 +113,11 @@ vendor/bin/mftf build:project --MAGENTO_BASE_URL=http://magento.local/ --MAGENTO #### Description -Diagnose MFTF configuration and setup +Diagnose MFTF configuration and setup. Currently this command will check the following: +- Verify admin credentials are valid. Allowing MFTF authenticates and runs API requests to Magento through cURL +- Verify that Selenium is up and running and available for MFTF +- Verify that new session of browser can open Magento admin and store front urls +- Verify that MFTF can run MagentoCLI commands #### Usage diff --git a/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php b/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php index d75004fc2..4bd05b836 100644 --- a/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php @@ -18,23 +18,20 @@ use Magento\FunctionalTestingFramework\Util\ModuleResolver; use Magento\FunctionalTestingFramework\Module\MagentoWebDriver; use Magento\FunctionalTestingFramework\Module\MagentoWebDriverDoctor; +use Symfony\Component\Console\Style\SymfonyStyle; class DoctorCommand extends Command { const CODECEPTION_AUTOLOAD_FILE = PROJECT_ROOT . '/vendor/codeception/codeception/autoload.php'; const MFTF_CODECEPTION_CONFIG_FILE = ENV_FILE_PATH . 'codeception.yml'; const SUITE = 'functional'; - const COLOR_LIGHT_GREEN = "\e[1;32m"; - const COLOR_LIGHT_RED = "\e[1;31m"; - const COLOR_LIGHT_DEFAULT = "\e[1;39m"; - const COLOR_RESTORE = "\e[0m"; /** - * Command Output + * Console output style * - * @var OutputInterface + * @var SymfonyStyle */ - private $output; + private $ioStyle; /** * Exception Context @@ -63,17 +60,17 @@ protected function configure() * @param OutputInterface $output * @return integer * @throws TestFrameworkException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function execute(InputInterface $input, OutputInterface $output) { + // For output style + $this->ioStyle = new SymfonyStyle($input, $output); + $cmdStatus = true; // Config application $verbose = $output->isVerbose(); - $this->input = $input; - $this->output = $output; MftfApplicationConfig::create( false, MftfApplicationConfig::GENERATION_PHASE, @@ -126,14 +123,15 @@ private function checkAuthenticationToMagentoAdmin() { $result = false; try { - $this->output->writeln( - "\n" . self::COLOR_LIGHT_DEFAULT . "Authenticating admin account by API ..." . self::COLOR_RESTORE - ); + $this->ioStyle->text("Requesting API token for admin user through cURL ..."); ModuleResolver::getInstance()->getAdminToken(); - $this->output->writeln(self::COLOR_LIGHT_GREEN . 'Successful' . self::COLOR_RESTORE); + $this->ioStyle->success('Successful'); $result = true; } catch (TestFrameworkException $e) { - $this->output->writeln(self::COLOR_LIGHT_RED . $e->getMessage() . self::COLOR_RESTORE); + $this->ioStyle->error( + $e->getMessage() + . "\nPlease verify MAGENTO_ADMIN_USERNAME and MAGENTO_ADMIN_PASSWORD in .env." + ); } return $result; } @@ -148,14 +146,14 @@ private function checkAuthenticationToMagentoAdmin() */ private function checkContextOnStep($exceptionType, $message) { - $this->output->writeln("\n" . self::COLOR_LIGHT_DEFAULT. $message . self::COLOR_RESTORE); + $this->ioStyle->text($message . ' ...'); $this->runMagentoWebDriverDoctor(); if (isset($this->context[$exceptionType])) { - $this->output->writeln(self::COLOR_LIGHT_RED . $this->context[$exceptionType] . self::COLOR_RESTORE); + $this->ioStyle->error($this->context[$exceptionType]); return false; } else { - $this->output->writeln(self::COLOR_LIGHT_GREEN . 'Successful' . self::COLOR_RESTORE); + $this->ioStyle->success('Successful'); return true; } } diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php index 35fa37f03..082c2d7c6 100644 --- a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php @@ -94,12 +94,16 @@ private function connectToSeleniumServer() $this->httpProxy, $this->httpProxyPort ); + if (null !== $this->remoteWebDriver) { + return; + } } catch (\Exception $e) { - throw new TestFrameworkException( - "Failed to connect Selenium WebDriver at: {$this->wdHost}.\n" - . "Please make sure that Selenium Server is running." - ); } + + throw new TestFrameworkException( + "Failed to connect Selenium WebDriver at: {$this->wdHost}.\n" + . "Please make sure that Selenium Server is running." + ); } /** @@ -112,19 +116,21 @@ private function connectToSeleniumServer() private function loadPageAtUrl($url) { try { - // Open the web page at url first - $this->remoteWebDriver->get($url); - - // Execute Javascript to retrieve HTTP response code - $script = '' - . 'var xhr = new XMLHttpRequest();' - . "xhr.open('GET', '" . $url . "', false);" - . 'xhr.send(null); ' - . 'return xhr.status'; - $status = $this->remoteWebDriver->executeScript($script); - - if ($status === 200) { - return; + if (null !== $this->remoteWebDriver) { + // Open the web page at url first + $this->remoteWebDriver->get($url); + + // Execute Javascript to retrieve HTTP response code + $script = '' + . 'var xhr = new XMLHttpRequest();' + . "xhr.open('GET', '" . $url . "', false);" + . 'xhr.send(null); ' + . 'return xhr.status'; + $status = $this->remoteWebDriver->executeScript($script); + + if ($status === 200) { + return; + } } } catch (\Exception $e) { } diff --git a/src/Magento/FunctionalTestingFramework/_bootstrap.php b/src/Magento/FunctionalTestingFramework/_bootstrap.php index dd7cfd37d..e401123b6 100644 --- a/src/Magento/FunctionalTestingFramework/_bootstrap.php +++ b/src/Magento/FunctionalTestingFramework/_bootstrap.php @@ -16,7 +16,7 @@ } defined('PROJECT_ROOT') || define('PROJECT_ROOT', $projectRootPath); -$envFilePath = realpath($projectRootPath . '/dev/tests/acceptance/'); +$envFilePath = realpath($projectRootPath . '/dev/tests/acceptance/') . DIRECTORY_SEPARATOR; defined('ENV_FILE_PATH') || define('ENV_FILE_PATH', $envFilePath); //Load constants from .env file From de359cb99281e0f0cfd667f2aa9a100a2c078c45 Mon Sep 17 00:00:00 2001 From: Ji Lu Date: Tue, 19 Nov 2019 09:43:40 -0600 Subject: [PATCH 8/8] MQE-1257: MFTF doctor command --- .../Module/MagentoWebDriverDoctor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php index 082c2d7c6..98eb8bd4f 100644 --- a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriverDoctor.php @@ -137,7 +137,7 @@ private function loadPageAtUrl($url) throw new TestFrameworkException( "Failed to load page at url: $url\n" - . "Please check network connection for the browser running Selenium." + . "Please check Selenium Browser session have access to Magento instance." ); }