Skip to content

Commit 4d745cc

Browse files
author
Shashik.K.Singh
committed
MQE-2669 seprated a run:failed command to generate:failed and run:failed
1 parent 537fe57 commit 4d745cc

File tree

4 files changed

+191
-100
lines changed

4 files changed

+191
-100
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ dev/tests/docs/*
2020
dev/tests/_output
2121
dev/tests/functional.suite.yml
2222
/v2/
23+
dev/.credentials.example

src/Magento/FunctionalTestingFramework/Console/CommandList.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public function __construct(array $commands = [])
3636
'generate:tests' => new GenerateTestsCommand(),
3737
'generate:urn-catalog' => new GenerateDevUrnCommand(),
3838
'reset' => new CleanProjectCommand(),
39+
'generate:failed' => new GenerateTestFailedCommand(),
3940
'run:failed' => new RunTestFailedCommand(),
4041
'run:group' => new RunTestGroupCommand(),
4142
'run:manifest' => new RunManifestCommand(),
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
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 Magento\FunctionalTestingFramework\Config\MftfApplicationConfig;
11+
use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter;
12+
use Symfony\Component\Console\Input\ArrayInput;
13+
use Symfony\Component\Console\Input\InputInterface;
14+
use Symfony\Component\Console\Output\OutputInterface;
15+
use Symfony\Component\Process\Process;
16+
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
17+
use Symfony\Component\Console\Input\InputOption;
18+
19+
class GenerateTestFailedCommand extends BaseGenerateCommand
20+
{
21+
/**
22+
* Default Test group to signify not in suite
23+
*/
24+
const DEFAULT_TEST_GROUP = 'default';
25+
26+
/**
27+
* @var string
28+
*/
29+
private $testsReRunFile;
30+
31+
/**
32+
* @var array
33+
*/
34+
private $failedList = [];
35+
36+
/**
37+
* Configures the current command.
38+
*
39+
* @return void
40+
*/
41+
protected function configure()
42+
{
43+
$this->setName('generate:failed')
44+
->setDescription('Generate a set of tests failed');
45+
46+
parent::configure();
47+
}
48+
49+
/**
50+
* Executes the current command.
51+
*
52+
* @param InputInterface $input
53+
* @param OutputInterface $output
54+
* @return integer
55+
* @throws \Exception
56+
*
57+
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
58+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
59+
*/
60+
protected function execute(InputInterface $input, OutputInterface $output): int
61+
{
62+
$this->testsFailedFile = $this->getTestsOutputDir() . self::FAILED_FILE;
63+
$this->testsReRunFile = $this->getTestsOutputDir() . "rerun_tests";
64+
65+
$force = $input->getOption('force');
66+
$debug = $input->getOption('debug') ?? MftfApplicationConfig::LEVEL_DEVELOPER; // for backward compatibility
67+
$allowSkipped = $input->getOption('allow-skipped');
68+
$verbose = $output->isVerbose();
69+
70+
// Create Mftf Configuration
71+
MftfApplicationConfig::create(
72+
$force,
73+
MftfApplicationConfig::EXECUTION_PHASE,
74+
$verbose,
75+
$debug,
76+
$allowSkipped
77+
);
78+
79+
$testConfiguration = $this->getFailedTestList();
80+
81+
if ($testConfiguration === null) {
82+
// no failed tests found, run is a success
83+
return 0;
84+
}
85+
86+
$command = $this->getApplication()->find('generate:tests');
87+
$args = [
88+
'--tests' => $testConfiguration,
89+
'--force' => $force,
90+
'--remove' => true,
91+
'--debug' => $debug,
92+
'--allow-skipped' => $allowSkipped,
93+
'-v' => $verbose
94+
];
95+
$command->run(new ArrayInput($args), $output);
96+
$output->writeln("Test Failed Generated, now run:failed command");
97+
return 1;
98+
}
99+
100+
/**
101+
* Returns a json string of tests that failed on the last run
102+
*
103+
* @return string
104+
*/
105+
private function getFailedTestList()
106+
{
107+
$failedTestDetails = ['tests' => [], 'suites' => []];
108+
109+
if (realpath($this->testsFailedFile)) {
110+
$testList = $this->readFailedTestFile($this->testsFailedFile);
111+
112+
foreach ($testList as $test) {
113+
if (!empty($test)) {
114+
$this->writeFailedTestToFile($test, $this->testsReRunFile);
115+
$testInfo = explode(DIRECTORY_SEPARATOR, $test);
116+
$testName = explode(":", $testInfo[count($testInfo) - 1])[1];
117+
$suiteName = $testInfo[count($testInfo) - 2];
118+
119+
if ($suiteName === self::DEFAULT_TEST_GROUP) {
120+
array_push($failedTestDetails['tests'], $testName);
121+
} else {
122+
$suiteName = $this->sanitizeSuiteName($suiteName);
123+
$failedTestDetails['suites'] = array_merge_recursive(
124+
$failedTestDetails['suites'],
125+
[$suiteName => [$testName]]
126+
);
127+
}
128+
}
129+
}
130+
}
131+
if (empty($failedTestDetails['tests']) & empty($failedTestDetails['suites'])) {
132+
return null;
133+
}
134+
if (empty($failedTestDetails['tests'])) {
135+
$failedTestDetails['tests'] = null;
136+
}
137+
if (empty($failedTestDetails['suites'])) {
138+
$failedTestDetails['suites'] = null;
139+
}
140+
$testConfigurationJson = json_encode($failedTestDetails);
141+
return $testConfigurationJson;
142+
}
143+
144+
/**
145+
* Trim potential suite_parallel_0_G to suite_parallel
146+
*
147+
* @param string $suiteName
148+
* @return string
149+
*/
150+
private function sanitizeSuiteName($suiteName)
151+
{
152+
$suiteNameArray = explode("_", $suiteName);
153+
if (array_pop($suiteNameArray) === 'G') {
154+
if (is_numeric(array_pop($suiteNameArray))) {
155+
$suiteName = implode("_", $suiteNameArray);
156+
}
157+
}
158+
return $suiteName;
159+
}
160+
161+
/**
162+
* Returns an array of tests read from the failed test file in _output
163+
*
164+
* @param string $filePath
165+
* @return array|boolean
166+
*/
167+
private function readFailedTestFile($filePath)
168+
{
169+
return file($filePath, FILE_IGNORE_NEW_LINES);
170+
}
171+
172+
/**
173+
* Writes the test name to a file if it does not already exist
174+
*
175+
* @param string $test
176+
* @param string $filePath
177+
* @return void
178+
*/
179+
private function writeFailedTestToFile($test, $filePath)
180+
{
181+
if (file_exists($filePath)) {
182+
if (strpos(file_get_contents($filePath), $test) === false) {
183+
file_put_contents($filePath, "\n" . $test, FILE_APPEND);
184+
}
185+
} else {
186+
file_put_contents($filePath, $test . "\n");
187+
}
188+
}
189+
}

src/Magento/FunctionalTestingFramework/Console/RunTestFailedCommand.php

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ class RunTestFailedCommand extends BaseGenerateCommand
2323
*/
2424
const DEFAULT_TEST_GROUP = 'default';
2525

26-
/**
27-
* @var string
28-
*/
29-
private $testsReRunFile;
30-
3126
/**
3227
* @var string
3328
*/
@@ -64,45 +59,11 @@ protected function configure()
6459
*/
6560
protected function execute(InputInterface $input, OutputInterface $output): int
6661
{
67-
$this->testsFailedFile = $this->getTestsOutputDir() . self::FAILED_FILE;
68-
$this->testsReRunFile = $this->getTestsOutputDir() . "rerun_tests";
6962
$this->testsManifestFile= FilePathFormatter::format(TESTS_MODULE_PATH) .
7063
"_generated" .
7164
DIRECTORY_SEPARATOR .
7265
"testManifest.txt";
7366

74-
$force = $input->getOption('force');
75-
$debug = $input->getOption('debug') ?? MftfApplicationConfig::LEVEL_DEVELOPER; // for backward compatibility
76-
$allowSkipped = $input->getOption('allow-skipped');
77-
$verbose = $output->isVerbose();
78-
79-
// Create Mftf Configuration
80-
MftfApplicationConfig::create(
81-
$force,
82-
MftfApplicationConfig::EXECUTION_PHASE,
83-
$verbose,
84-
$debug,
85-
$allowSkipped
86-
);
87-
88-
$testConfiguration = $this->getFailedTestList();
89-
90-
if ($testConfiguration === null) {
91-
// no failed tests found, run is a success
92-
return 0;
93-
}
94-
95-
$command = $this->getApplication()->find('generate:tests');
96-
$args = [
97-
'--tests' => $testConfiguration,
98-
'--force' => $force,
99-
'--remove' => true,
100-
'--debug' => $debug,
101-
'--allow-skipped' => $allowSkipped,
102-
'-v' => $verbose
103-
];
104-
$command->run(new ArrayInput($args), $output);
105-
10667
$testManifestList = $this->readTestManifestFile();
10768
$returnCode = 0;
10869
for ($i = 0; $i < count($testManifestList); $i++) {
@@ -142,67 +103,6 @@ function ($type, $buffer) use ($output) {
142103
return $returnCode;
143104
}
144105

145-
/**
146-
* Returns a json string of tests that failed on the last run
147-
*
148-
* @return string
149-
*/
150-
private function getFailedTestList()
151-
{
152-
$failedTestDetails = ['tests' => [], 'suites' => []];
153-
154-
if (realpath($this->testsFailedFile)) {
155-
$testList = $this->readFailedTestFile($this->testsFailedFile);
156-
157-
foreach ($testList as $test) {
158-
if (!empty($test)) {
159-
$this->writeFailedTestToFile($test, $this->testsReRunFile);
160-
$testInfo = explode(DIRECTORY_SEPARATOR, $test);
161-
$testName = explode(":", $testInfo[count($testInfo) - 1])[1];
162-
$suiteName = $testInfo[count($testInfo) - 2];
163-
164-
if ($suiteName === self::DEFAULT_TEST_GROUP) {
165-
array_push($failedTestDetails['tests'], $testName);
166-
} else {
167-
$suiteName = $this->sanitizeSuiteName($suiteName);
168-
$failedTestDetails['suites'] = array_merge_recursive(
169-
$failedTestDetails['suites'],
170-
[$suiteName => [$testName]]
171-
);
172-
}
173-
}
174-
}
175-
}
176-
if (empty($failedTestDetails['tests']) & empty($failedTestDetails['suites'])) {
177-
return null;
178-
}
179-
if (empty($failedTestDetails['tests'])) {
180-
$failedTestDetails['tests'] = null;
181-
}
182-
if (empty($failedTestDetails['suites'])) {
183-
$failedTestDetails['suites'] = null;
184-
}
185-
$testConfigurationJson = json_encode($failedTestDetails);
186-
return $testConfigurationJson;
187-
}
188-
189-
/**
190-
* Trim potential suite_parallel_0_G to suite_parallel
191-
*
192-
* @param string $suiteName
193-
* @return string
194-
*/
195-
private function sanitizeSuiteName($suiteName)
196-
{
197-
$suiteNameArray = explode("_", $suiteName);
198-
if (array_pop($suiteNameArray) === 'G') {
199-
if (is_numeric(array_pop($suiteNameArray))) {
200-
$suiteName = implode("_", $suiteNameArray);
201-
}
202-
}
203-
return $suiteName;
204-
}
205-
206106
/**
207107
* Returns an array of run commands read from the manifest file created post generation
208108
*

0 commit comments

Comments
 (0)