diff --git a/.env.example b/.env.example
index 536ea1fa5..ddecfaa34 100644
--- a/.env.example
+++ b/.env.example
@@ -5,9 +5,9 @@
MAGENTO_BASE_URL=http://devdocs.magento.com/
#*** Set the Admin Username and Password for your Magento instance ***#
-MAGENTO_BACKEND_NAME=
-MAGENTO_ADMIN_USERNAME=
-MAGENTO_ADMIN_PASSWORD=
+MAGENTO_BACKEND_NAME=admin
+MAGENTO_ADMIN_USERNAME=admin
+MAGENTO_ADMIN_PASSWORD=123123q
#*** Path to CLI entry point and command parameter name. Uncomment and change if folder structure differs from standard Magento installation
#MAGENTO_CLI_COMMAND_PATH=dev/tests/acceptance/utils/command.php
diff --git a/RoboFile.php b/RoboFile.php
index a085095d1..2bd0077c4 100644
--- a/RoboFile.php
+++ b/RoboFile.php
@@ -33,6 +33,7 @@ function cloneFiles()
*/
function buildProject()
{
+ $this->writeln("This command will be removed in MFTF v3.0.0. Please use bin/mftf build:project instead.\n");
$this->cloneFiles();
$this->_exec('vendor'. DIRECTORY_SEPARATOR .'bin'. DIRECTORY_SEPARATOR .'codecept build');
}
diff --git a/bin/mftf b/bin/mftf
new file mode 100755
index 000000000..623e3bc61
--- /dev/null
+++ b/bin/mftf
@@ -0,0 +1,30 @@
+#!/usr/bin/env php
+
+setName('Magento Functional Testing Framework CLI');
+ $application->setVersion('1.0.0');
+ $application->add(new Magento\FunctionalTestingFramework\Console\SetupEnvCommand());
+ $application->add(new Magento\FunctionalTestingFramework\Console\BuildProjectCommand());
+ $application->run();
+} catch (\Exception $e) {
+ while ($e) {
+ echo $e->getMessage();
+ echo $e->getTraceAsString();
+ echo "\n\n";
+ $e = $e->getPrevious();
+ }
+ exit(1);
+}
diff --git a/bootstrap.php b/bootstrap.php
new file mode 100644
index 000000000..7a708e8a8
--- /dev/null
+++ b/bootstrap.php
@@ -0,0 +1,8 @@
+setName('build:project');
+ $this->setDescription('Generate configuration files for the project. Build the Codeception project.');
+ $this->envProcessor = new EnvProcessor(BP . DIRECTORY_SEPARATOR . '.env');
+ $env = $this->envProcessor->getEnv();
+ foreach ($env as $key => $value) {
+ $this->addOption($key, null, InputOption::VALUE_REQUIRED, '', $value);
+ }
+ }
+
+ /**
+ * Executes the current command.
+ *
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ * @return void
+ * @throws \Symfony\Component\Console\Exception\LogicException
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $fileSystem = new Filesystem();
+ $fileSystem->copy(
+ BP . DIRECTORY_SEPARATOR . 'codeception.dist.yml',
+ BP . DIRECTORY_SEPARATOR . 'codeception.yml'
+ );
+ $output->writeln("codeception.yml configuration successfully applied.\n");
+ $fileSystem->copy(
+ BP . DIRECTORY_SEPARATOR . 'dev' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR .
+ 'functional' . DIRECTORY_SEPARATOR . 'MFTF.suite.dist.yml',
+ BP . DIRECTORY_SEPARATOR . 'dev' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR .
+ 'functional' . DIRECTORY_SEPARATOR . 'MFTF.suite.yml'
+ );
+ $output->writeln("MFTF.suite.yml configuration successfully applied.\n");
+
+ $setupEnvCommand = new SetupEnvCommand();
+ $commandInput = [];
+ $options = $input->getOptions();
+ $env = array_keys($this->envProcessor->getEnv());
+ foreach ($options as $key => $value) {
+ if (in_array($key, $env)) {
+ $commandInput['--' . $key] = $value;
+ }
+ }
+ $commandInput = new ArrayInput($commandInput);
+ $setupEnvCommand->run($commandInput, $output);
+
+ $process = new Process('vendor/bin/codecept build');
+ $process->run();
+ if ($process->isSuccessful()) {
+ $output->writeln("Codeception build run successfully.\n");
+ }
+
+ $output->writeln('The project built successfully.');
+ }
+}
diff --git a/src/Magento/FunctionalTestingFramework/Console/SetupEnvCommand.php b/src/Magento/FunctionalTestingFramework/Console/SetupEnvCommand.php
new file mode 100644
index 000000000..e0ef6053a
--- /dev/null
+++ b/src/Magento/FunctionalTestingFramework/Console/SetupEnvCommand.php
@@ -0,0 +1,64 @@
+setName('setup:env');
+ $this->setDescription("Generate .env file.");
+ $this->envProcessor = new EnvProcessor(BP . DIRECTORY_SEPARATOR . '.env');
+ $env = $this->envProcessor->getEnv();
+ foreach ($env as $key => $value) {
+ $this->addOption($key, null, InputOption::VALUE_REQUIRED, '', $value);
+ }
+ }
+
+ /**
+ * Executes the current command.
+ *
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ * @return void
+ * @throws \Symfony\Component\Console\Exception\LogicException
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $config = $this->envProcessor->getEnv();
+ $userEnv = [];
+ foreach ($config as $key => $value) {
+ if ($input->getOption($key) === '') {
+ throw new InvalidOptionException(sprintf("Parameter $key cannot be empty.", $key));
+ }
+ $userEnv[$key] = $input->getOption($key);
+ }
+ $this->envProcessor->putEnvFile($userEnv);
+ $output->writeln(".env configuration successfully applied.\n");
+ }
+}
diff --git a/src/Magento/FunctionalTestingFramework/Util/Env/EnvProcessor.php b/src/Magento/FunctionalTestingFramework/Util/Env/EnvProcessor.php
new file mode 100644
index 000000000..7129ff091
--- /dev/null
+++ b/src/Magento/FunctionalTestingFramework/Util/Env/EnvProcessor.php
@@ -0,0 +1,99 @@
+envFile = $envFile;
+ $this->envExampleFile = $envFile . '.example';
+ }
+
+ /**
+ * Serves for parsing '.env.example' file into associative array.
+ *
+ * @return array
+ */
+ public function parseEnvFile(): array
+ {
+ $envLines = file(
+ $this->envExampleFile,
+ FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES
+ );
+ $env = [];
+ foreach ($envLines as $line) {
+ // do not use commented out lines
+ if (strpos($line, '#') !== 0) {
+ list($key, $value) = explode('=', $line);
+ $env[$key] = $value;
+ }
+ }
+ return $env;
+ }
+
+ /**
+ * Serves for putting array with environment variables into .env file.
+ *
+ * @param array $config
+ * @return void
+ */
+ public function putEnvFile(array $config = [])
+ {
+ $envData = '';
+ foreach ($config as $key => $value) {
+ $envData .= $key . '=' . $value . PHP_EOL;
+ }
+ file_put_contents($this->envFile, $envData);
+ }
+
+ /**
+ * Retrieves '.env.example' file as associative array.
+ *
+ * @return array
+ */
+ public function getEnv(): array
+ {
+ if (empty($this->env)) {
+ $this->env = $this->parseEnvFile();
+ }
+ return $this->env;
+ }
+}