Skip to content

MQE-1257: MFTF Doctor command #500

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 19, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions dev/tests/functional/standalone_bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 14 additions & 13 deletions src/Magento/FunctionalTestingFramework/Console/CommandList.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
159 changes: 159 additions & 0 deletions src/Magento/FunctionalTestingFramework/Console/TroubleShootCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types = 1);

namespace Magento\FunctionalTestingFramework\Console;

use Codeception\Configuration;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Codeception\SuiteManager;
use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig;
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Magento\FunctionalTestingFramework\Util\ModuleResolver;

class TroubleShootCommand 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
*
* @var OutputInterface
*/
private $output;

/**
* Configures the current command.
*
* @return void
*/
protected function configure()
{
$this->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 integer
* @throws TestFrameworkException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
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) {
return 0;
} else {
return 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;
}
}
34 changes: 34 additions & 0 deletions src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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();
}
}

/**
Expand Down Expand Up @@ -826,6 +834,32 @@ 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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 5 additions & 3 deletions src/Magento/FunctionalTestingFramework/_bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down