Skip to content

Commit 037d8aa

Browse files
committed
MQE-1626: bin/mftf run:manifest
- Initial implementation
1 parent 0fe97bb commit 037d8aa

File tree

2 files changed

+145
-0
lines changed

2 files changed

+145
-0
lines changed

src/Magento/FunctionalTestingFramework/Console/CommandList.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function __construct(array $commands = [])
3737
'run:test' => new RunTestCommand(),
3838
'run:group' => new RunTestGroupCommand(),
3939
'run:failed' => new RunTestFailedCommand(),
40+
'run:manifest' => new RunManifestCommand(),
4041
'setup:env' => new SetupEnvCommand(),
4142
'upgrade:tests' => new UpgradeTestsCommand(),
4243
'generate:docs' => new GenerateDocsCommand(),
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
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 Symfony\Component\Console\Command\Command;
11+
use Symfony\Component\Console\Input\InputArgument;
12+
use Symfony\Component\Console\Input\InputInterface;
13+
use Symfony\Component\Console\Output\OutputInterface;
14+
use Symfony\Component\Process\Process;
15+
16+
class RunManifestCommand extends Command
17+
{
18+
/**
19+
* The return code. Determined by all tests that run.
20+
*
21+
* @var integer
22+
*/
23+
private $returnCode = 0;
24+
25+
/**
26+
* A list of tests that failed.
27+
* Eg: "tests/functional/tests/MFTF/_generated/default/AdminLoginTestCest.php:AdminLoginTest"
28+
*
29+
* @var string[]
30+
*/
31+
private $failedTests = [];
32+
33+
/**
34+
* Configure the run:manifest command.
35+
*
36+
* @return void
37+
*/
38+
protected function configure()
39+
{
40+
$this->setName("run:manifest")
41+
->setDescription("runs a manifest file")
42+
->addArgument("path", InputArgument::REQUIRED, "path to a manifest file");
43+
}
44+
45+
/**
46+
* Executes the run:manifest command.
47+
*
48+
* @param InputInterface $input
49+
* @param OutputInterface $output
50+
* @return integer
51+
*/
52+
protected function execute(InputInterface $input, OutputInterface $output): int
53+
{
54+
$manifestFile = file($input->getArgument("path"), FILE_IGNORE_NEW_LINES);
55+
56+
// Delete the Codeception failed file just in case it exists from any previous test runs
57+
$this->deleteFailedFile();
58+
59+
foreach ($manifestFile as $manifestLine) {
60+
if (empty($manifestLine)) {
61+
continue;
62+
}
63+
64+
$this->runManifestLine($manifestLine, $output);
65+
$this->aggregateFailed();
66+
}
67+
68+
if (!empty($this->failedTests)) {
69+
$this->deleteFailedFile();
70+
$this->writeFailedFile();
71+
}
72+
73+
return $this->returnCode;
74+
}
75+
76+
/**
77+
* Runs a test (or group) line from the manifest file
78+
*
79+
* @param string $manifestLine
80+
* @param OutputInterface $output
81+
* @return void
82+
*
83+
* @SuppressWarnings(PHPMD.UnusedLocalVariable) Need this because of the unused $type variable in the closure
84+
*/
85+
private function runManifestLine(string $manifestLine, OutputInterface $output)
86+
{
87+
$codeceptionCommand = realpath(PROJECT_ROOT . "/vendor/bin/codecept")
88+
. " run functional --verbose --steps "
89+
. $manifestLine;
90+
91+
// run the codecept command in a sub process
92+
$process = new Process($codeceptionCommand);
93+
$process->setWorkingDirectory(TESTS_BP);
94+
$process->setIdleTimeout(600);
95+
$process->setTimeout(0);
96+
$subReturnCode = $process->run(function ($type, $buffer) use ($output) {
97+
$output->write($buffer);
98+
});
99+
$this->returnCode = max($this->returnCode, $subReturnCode);
100+
}
101+
102+
/**
103+
* Keeps track of any tests that failed while running the manifest file.
104+
*
105+
* Each codecept command executions overwrites the failed file. Since we are running multiple codecept commands,
106+
* we need to hold on to any failures in order to write a final failed file containing all tests.
107+
*
108+
* @return void
109+
*/
110+
private function aggregateFailed()
111+
{
112+
if (file_exists(RunTestFailedCommand::TESTS_FAILED_FILE)) {
113+
$currentFile = file(RunTestFailedCommand::TESTS_FAILED_FILE, FILE_IGNORE_NEW_LINES);
114+
$this->failedTests = array_merge(
115+
$this->failedTests,
116+
$currentFile
117+
);
118+
}
119+
}
120+
121+
/**
122+
* Delete the Codeception failed file.
123+
*
124+
* @return void
125+
*/
126+
private function deleteFailedFile()
127+
{
128+
if (file_exists(RunTestFailedCommand::TESTS_FAILED_FILE)) {
129+
unlink(RunTestFailedCommand::TESTS_FAILED_FILE);
130+
}
131+
}
132+
133+
/**
134+
* Writes any tests that failed to the Codeception failed file.
135+
*
136+
* @return void
137+
*/
138+
private function writeFailedFile()
139+
{
140+
foreach ($this->failedTests as $test) {
141+
file_put_contents(RunTestFailedCommand::TESTS_FAILED_FILE, $test . "\n", FILE_APPEND);
142+
}
143+
}
144+
}

0 commit comments

Comments
 (0)