Skip to content

Commit 8e04580

Browse files
committed
MQE-2110: MFTF command to pause test execution
1 parent 0dcc9fa commit 8e04580

8 files changed

+223
-52
lines changed

src/Magento/FunctionalTestingFramework/Console/BaseGenerateCommand.php

+23
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,24 @@
1414
use Symfony\Component\Console\Command\Command;
1515
use Symfony\Component\Console\Input\InputInterface;
1616
use Symfony\Component\Console\Input\InputOption;
17+
use Symfony\Component\Console\Input\StringInput;
1718
use Symfony\Component\Console\Output\OutputInterface;
1819
use Magento\FunctionalTestingFramework\Util\Filesystem\DirSetupUtil;
1920
use Magento\FunctionalTestingFramework\Util\TestGenerator;
2021
use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig;
2122
use Magento\FunctionalTestingFramework\Suite\Handlers\SuiteObjectHandler;
2223
use Symfony\Component\Console\Style\SymfonyStyle;
2324

25+
/**
26+
* Class BaseGenerateCommand
27+
* @package Magento\FunctionalTestingFramework\Console
28+
*
29+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
30+
*/
2431
class BaseGenerateCommand extends Command
2532
{
2633
const MFTF_NOTICES = "Placeholder text for MFTF notices\n";
34+
const CODECEPT_RUN_COMMAND = 'codecept:run functional ';
2735

2836
/**
2937
* Enable pause()
@@ -242,4 +250,19 @@ protected function pauseEnabled()
242250
}
243251
return $this->enablePause;
244252
}
253+
254+
/**
255+
* Runs the bin/mftf codecept:run command and returns exit code
256+
*
257+
* @param string $command
258+
* @param OutputInterface $output
259+
* @return integer
260+
* @throws \Exception
261+
*/
262+
protected function codeceptRunTest(string $command, OutputInterface $output)
263+
{
264+
$input = new StringInput($command);
265+
$command = $this->getApplication()->find('codecept:run');
266+
return $command->run($input, $output);
267+
}
245268
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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\Codecept;
9+
10+
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
11+
use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter;
12+
use Symfony\Component\Console\Input\InputInterface;
13+
use Symfony\Component\Console\Input\ArgvInput;
14+
15+
class CodeceptCommandUtil
16+
{
17+
const CODECEPTION_AUTOLOAD_FILE = PROJECT_ROOT . '/vendor/codeception/codeception/autoload.php';
18+
19+
/**
20+
* Current working directory
21+
*
22+
* @var string
23+
*/
24+
private $cwd = null;
25+
26+
/**
27+
* Setup Codeception
28+
*
29+
* @param InputInterface $input
30+
* @return void
31+
*/
32+
public function setup(InputInterface $input)
33+
{
34+
require_once realpath(self::CODECEPTION_AUTOLOAD_FILE);
35+
36+
$tokens = preg_split('{\\s+}', $input->__toString());
37+
$tokens[0] = str_replace('codecept:', '', $tokens[0]);
38+
\Closure::bind(function &(ArgvInput $input) use ($tokens) {
39+
return $input->setTokens($tokens);
40+
}, null, ArgvInput::class);
41+
}
42+
43+
/**
44+
* Save Codeception working directory
45+
*
46+
* @return void
47+
* @throws TestFrameworkException
48+
*/
49+
public function setCodeceptCwd()
50+
{
51+
$this->cwd = getcwd();
52+
chdir(FilePathFormatter::format(TESTS_BP, false));
53+
}
54+
55+
/**
56+
* Restore current working directory
57+
*
58+
* @return void
59+
*/
60+
public function restoreCwd()
61+
{
62+
if ($this->cwd) {
63+
chdir($this->cwd);
64+
}
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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\Command\Run;
11+
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
12+
use Symfony\Component\Console\Input\InputInterface;
13+
use Symfony\Component\Console\Output\OutputInterface;
14+
use Magento\FunctionalTestingFramework\Console\Codecept\CodeceptCommandUtil;
15+
16+
class CodeceptRunCommand extends Run
17+
{
18+
/**
19+
* Configures the current command
20+
*
21+
* @return void
22+
*/
23+
protected function configure()
24+
{
25+
$this->setName('codecept:run')
26+
->setDescription(
27+
"Wrapper command to codecept:run. See https://codeception.com/docs/reference/Commands"
28+
);
29+
30+
parent::configure();
31+
}
32+
33+
/**
34+
* Executes the current command
35+
*
36+
* @param InputInterface $input
37+
* @param OutputInterface $output
38+
* @return integer
39+
* @throws \Exception
40+
*/
41+
public function execute(InputInterface $input, OutputInterface $output): int
42+
{
43+
$commandUtil = new CodeceptCommandUtil();
44+
$commandUtil->setup($input);
45+
$commandUtil->setCodeceptCwd();
46+
47+
try {
48+
$exitCode = parent::execute($input, $output);
49+
} catch (\Exception $e) {
50+
throw new TestFrameworkException(
51+
'Make sure cest files are generated before running bin/mftf '
52+
. $this->getName()
53+
. PHP_EOL
54+
. $e->getMessage()
55+
);
56+
}
57+
58+
$commandUtil->restoreCwd();
59+
return $exitCode;
60+
}
61+
}

src/Magento/FunctionalTestingFramework/Console/CommandList.php

+1
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+
'codecept:run' => new CodeceptRunCommand(),
3334
'doctor' => new DoctorCommand(),
3435
'generate:suite' => new GenerateSuiteCommand(),
3536
'generate:tests' => new GenerateTestsCommand(),

src/Magento/FunctionalTestingFramework/Console/RunManifestCommand.php

+19-14
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Symfony\Component\Console\Command\Command;
1212
use Symfony\Component\Console\Input\InputArgument;
1313
use Symfony\Component\Console\Input\InputInterface;
14+
use Symfony\Component\Console\Input\StringInput;
1415
use Symfony\Component\Console\Output\OutputInterface;
1516
use Symfony\Component\Process\Process;
1617
use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter;
@@ -103,28 +104,32 @@ protected function execute(InputInterface $input, OutputInterface $output): int
103104
* @param string $manifestLine
104105
* @param OutputInterface $output
105106
* @return void
107+
* @throws \Exception
106108
*
107109
* @SuppressWarnings(PHPMD.UnusedLocalVariable) Need this because of the unused $type variable in the closure
108110
*/
109111
private function runManifestLine(string $manifestLine, OutputInterface $output)
110112
{
111-
$codeceptionCommand = realpath(PROJECT_ROOT . "/vendor/bin/codecept") . " run functional --verbose --steps ";
112113
if (getenv('ENABLE_PAUSE') === 'true') {
113-
$codeceptionCommand .= ' --debug';
114+
$codeceptionCommand = BaseGenerateCommand::CODECEPT_RUN_COMMAND
115+
. '--verbose --steps --debug' . $manifestLine;
116+
$input = new StringInput($codeceptionCommand);
117+
$command = $this->getApplication()->find('codecept:run');
118+
$subReturnCode = $command->run($input, $output);
119+
} else {
120+
$codeceptionCommand = realpath(PROJECT_ROOT . "/vendor/bin/codecept")
121+
. " run functional --verbose --steps " . $manifestLine;
122+
123+
// run the codecept command in a sub process
124+
$process = new Process($codeceptionCommand);
125+
$process->setWorkingDirectory(TESTS_BP);
126+
$process->setIdleTimeout(600);
127+
$process->setTimeout(0);
128+
$subReturnCode = $process->run(function ($type, $buffer) use ($output) {
129+
$output->write($buffer);
130+
});
114131
}
115-
$codeceptionCommand .= $manifestLine;
116132

117-
// run the codecept command in a sub process
118-
$process = new Process($codeceptionCommand);
119-
$process->setWorkingDirectory(TESTS_BP);
120-
$process->setIdleTimeout(600);
121-
$process->setTimeout(0);
122-
if (getenv('ENABLE_PAUSE') === 'true') {
123-
$process->setInput(STDIN);
124-
}
125-
$subReturnCode = $process->run(function ($type, $buffer) use ($output) {
126-
$output->write($buffer);
127-
});
128133
$this->returnCode = max($this->returnCode, $subReturnCode);
129134
}
130135

src/Magento/FunctionalTestingFramework/Console/RunTestCommand.php

+24-10
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int
119119
* @param OutputInterface $output
120120
* @return void
121121
* @throws TestFrameworkException
122+
* @throws \Exception
122123
*/
123124
private function runTests(array $tests, OutputInterface $output)
124125
{
125-
$codeceptionCommand = realpath(PROJECT_ROOT . '/vendor/bin/codecept') . ' run functional ';
126+
if ($this->pauseEnabled()) {
127+
$codeceptionCommand = self::CODECEPT_RUN_COMMAND;
128+
} else {
129+
$codeceptionCommand = realpath(PROJECT_ROOT . '/vendor/bin/codecept') . ' run functional ';
130+
}
131+
126132
$testsDirectory = FilePathFormatter::format(TESTS_MODULE_PATH) .
127133
TestGenerator::GENERATED_DIR .
128134
DIRECTORY_SEPARATOR .
@@ -136,11 +142,14 @@ private function runTests(array $tests, OutputInterface $output)
136142
$testName . " is not available under " . $testsDirectory
137143
);
138144
}
139-
$fullCommand = $codeceptionCommand . $testsDirectory . $testName . ' --verbose --steps';
145+
140146
if ($this->pauseEnabled()) {
141-
$fullCommand .= ' --debug';
147+
$fullCommand = $codeceptionCommand . $testsDirectory . $testName . ' --verbose --steps --debug';
148+
$this->returnCode = max($this->returnCode, $this->codeceptRunTest($fullCommand, $output));
149+
} else {
150+
$fullCommand = $codeceptionCommand . $testsDirectory . $testName . ' --verbose --steps';
151+
$this->returnCode = max($this->returnCode, $this->executeTestCommand($fullCommand, $output));
142152
}
143-
$this->returnCode = max($this->returnCode, $this->executeTestCommand($fullCommand, $output));
144153
}
145154
}
146155

@@ -150,17 +159,24 @@ private function runTests(array $tests, OutputInterface $output)
150159
* @param array $suitesConfig
151160
* @param OutputInterface $output
152161
* @return void
162+
* @throws \Exception
153163
*/
154164
private function runTestsInSuite(array $suitesConfig, OutputInterface $output)
155165
{
156-
$codeceptionCommand = realpath(PROJECT_ROOT . '/vendor/bin/codecept') . ' run functional --verbose --steps ';
157166
if ($this->pauseEnabled()) {
158-
$codeceptionCommand .= ' --debug';
167+
$codeceptionCommand = self::CODECEPT_RUN_COMMAND . '--verbose --steps --debug';
168+
} else {
169+
$codeceptionCommand = realpath(PROJECT_ROOT . '/vendor/bin/codecept')
170+
. ' run functional --verbose --steps ';
159171
}
160172
//for tests in suites, run them as a group to run before and after block
161173
foreach (array_keys($suitesConfig) as $suite) {
162174
$fullCommand = $codeceptionCommand . " -g {$suite}";
163-
$this->returnCode = max($this->returnCode, $this->executeTestCommand($fullCommand, $output));
175+
if ($this->pauseEnabled()) {
176+
$this->returnCode = max($this->returnCode, $this->codeceptRunTest($fullCommand, $output));
177+
} else {
178+
$this->returnCode = max($this->returnCode, $this->executeTestCommand($fullCommand, $output));
179+
}
164180
}
165181
}
166182

@@ -179,9 +195,7 @@ private function executeTestCommand(string $command, OutputInterface $output)
179195
$process->setWorkingDirectory(TESTS_BP);
180196
$process->setIdleTimeout(600);
181197
$process->setTimeout(0);
182-
if ($this->pauseEnabled()) {
183-
$process->setInput(STDIN);
184-
}
198+
185199
return $process->run(function ($type, $buffer) use ($output) {
186200
$output->write($buffer);
187201
});

src/Magento/FunctionalTestingFramework/Console/RunTestFailedCommand.php

+15-15
Original file line numberDiff line numberDiff line change
@@ -117,24 +117,24 @@ protected function execute(InputInterface $input, OutputInterface $output): int
117117
$testManifestList = $this->readTestManifestFile();
118118
$returnCode = 0;
119119
foreach ($testManifestList as $testCommand) {
120-
$codeceptionCommand = realpath(PROJECT_ROOT . '/vendor/bin/codecept') . ' run functional ';
121-
$codeceptionCommand .= $testCommand;
122120
if ($this->pauseEnabled()) {
123-
$codeceptionCommand .= ' --debug';
121+
$codeceptionCommand = self::CODECEPT_RUN_COMMAND . $testCommand . ' --debug';
122+
$this->codeceptRunTest($codeceptionCommand, $output);
123+
} else {
124+
$codeceptionCommand = realpath(PROJECT_ROOT . '/vendor/bin/codecept') . ' run functional ';
125+
$codeceptionCommand .= $testCommand;
126+
127+
$process = new Process($codeceptionCommand);
128+
$process->setWorkingDirectory(TESTS_BP);
129+
$process->setIdleTimeout(600);
130+
$process->setTimeout(0);
131+
$returnCode = max($returnCode, $process->run(
132+
function ($type, $buffer) use ($output) {
133+
$output->write($buffer);
134+
}
135+
));
124136
}
125137

126-
$process = new Process($codeceptionCommand);
127-
$process->setWorkingDirectory(TESTS_BP);
128-
$process->setIdleTimeout(600);
129-
$process->setTimeout(0);
130-
if ($this->pauseEnabled()) {
131-
$process->setInput(STDIN);
132-
}
133-
$returnCode = max($returnCode, $process->run(
134-
function ($type, $buffer) use ($output) {
135-
$output->write($buffer);
136-
}
137-
));
138138
if (file_exists($this->testsFailedFile)) {
139139
$this->failedList = array_merge(
140140
$this->failedList,

src/Magento/FunctionalTestingFramework/Console/RunTestGroupCommand.php

+14-13
Original file line numberDiff line numberDiff line change
@@ -94,29 +94,30 @@ protected function execute(InputInterface $input, OutputInterface $output): int
9494
$command->run(new ArrayInput($args), $output);
9595
}
9696

97-
$commandString = realpath(PROJECT_ROOT . '/vendor/bin/codecept') . ' run functional --verbose --steps';
9897
if ($this->pauseEnabled()) {
99-
$commandString .= ' --debug';
98+
$commandString = self::CODECEPT_RUN_COMMAND . '--verbose --steps --debug';
99+
} else {
100+
$commandString = realpath(PROJECT_ROOT . '/vendor/bin/codecept') . ' run functional --verbose --steps';
100101
}
101102

102103
$exitCode = -1;
103104
$returnCodes = [];
104105
foreach ($groups as $group) {
105106
$codeceptionCommandString = $commandString . " -g {$group}";
106107

107-
$process = new Process($codeceptionCommandString);
108-
$process->setWorkingDirectory(TESTS_BP);
109-
$process->setIdleTimeout(600);
110-
$process->setTimeout(0);
111108
if ($this->pauseEnabled()) {
112-
$process->setInput(STDIN);
109+
$returnCodes[] = $this->codeceptRunTest($codeceptionCommandString, $output);
110+
} else {
111+
$process = new Process($codeceptionCommandString);
112+
$process->setWorkingDirectory(TESTS_BP);
113+
$process->setIdleTimeout(600);
114+
$process->setTimeout(0);
115+
$returnCodes[] = $process->run(
116+
function ($type, $buffer) use ($output) {
117+
$output->write($buffer);
118+
}
119+
);
113120
}
114-
115-
$returnCodes[] = $process->run(
116-
function ($type, $buffer) use ($output) {
117-
$output->write($buffer);
118-
}
119-
);
120121
}
121122

122123
foreach ($returnCodes as $returnCode) {

0 commit comments

Comments
 (0)