Skip to content

Commit 00caa60

Browse files
committed
MQE-1376: [SPIKE] Investigate Self-Documentation for MFTF
- Added some mild documentation for action groups
1 parent 44aecc6 commit 00caa60

File tree

10 files changed

+430
-4
lines changed

10 files changed

+430
-4
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ codeception.yml
1515
dev/tests/functional/MFTF.suite.yml
1616
dev/tests/functional/_output
1717
dev/mftf.log
18-
dev/tests/mftf.log
18+
dev/tests/mftf.log
19+
dev/tests/docs/*

dev/tests/unit/Util/ActionGroupObjectBuilder.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ class ActionGroupObjectBuilder
2727
*/
2828
private $actionObjects = [];
2929

30+
/**
31+
* Action Group Object Builder default entity annotations.
32+
*
33+
* @var array
34+
*/
35+
private $annotations = [];
36+
3037
/**
3138
* Action Group Object Builder default entity arguments.
3239
*
@@ -108,6 +115,7 @@ public function build()
108115
{
109116
return new ActionGroupObject(
110117
$this->name,
118+
$this->annotations,
111119
$this->arguments,
112120
$this->actionObjects,
113121
$this->extends

src/Magento/FunctionalTestingFramework/Console/CommandList.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public function __construct(array $commands = [])
3838
'run:failed' => new RunTestFailedCommand(),
3939
'setup:env' => new SetupEnvCommand(),
4040
'upgrade:tests' => new UpgradeTestsCommand(),
41+
'generate:docs' => new GenerateDocsCommand(),
4142
] + $commands;
4243
}
4344

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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\Exceptions\TestFrameworkException;
12+
use Magento\FunctionalTestingFramework\Suite\SuiteGenerator;
13+
use Magento\FunctionalTestingFramework\Test\Handlers\ActionGroupObjectHandler;
14+
use Magento\FunctionalTestingFramework\Util\Manifest\ParallelTestManifest;
15+
use Magento\FunctionalTestingFramework\Util\Manifest\TestManifestFactory;
16+
use Magento\FunctionalTestingFramework\Util\TestGenerator;
17+
use Magento\FunctionalTestingFramework\Util\DocGenerator;
18+
use Symfony\Component\Console\Command\Command;
19+
use Symfony\Component\Console\Input\InputArgument;
20+
use Symfony\Component\Console\Input\InputInterface;
21+
use Symfony\Component\Console\Input\InputOption;
22+
use Symfony\Component\Console\Output\OutputInterface;
23+
24+
class GenerateDocsCommand extends Command
25+
{
26+
/**
27+
* Configures the current command.
28+
*
29+
* @return void
30+
*/
31+
protected function configure()
32+
{
33+
$this->setName('generate:docs')
34+
->setDescription('This command generates documentation for created MFTF files.')
35+
->addOption(
36+
"output",
37+
'o',
38+
InputOption::VALUE_REQUIRED,
39+
'Output Directory'
40+
)->addOption(
41+
"clean",
42+
'c',
43+
InputOption::VALUE_NONE,
44+
'Clean Output Directory'
45+
);
46+
}
47+
48+
/**
49+
* Executes the current command.
50+
*
51+
* @param InputInterface $input
52+
* @param OutputInterface $output
53+
* @return void
54+
* @throws TestFrameworkException
55+
* @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException
56+
* @throws \Magento\FunctionalTestingFramework\Exceptions\XmlException
57+
*/
58+
protected function execute(InputInterface $input, OutputInterface $output)
59+
{
60+
$config = $input->getOption('output');
61+
$clean = $input->getOption('clean');
62+
63+
$verbose = $output->isVerbose();
64+
65+
MftfApplicationConfig::create(
66+
true,
67+
MftfApplicationConfig::GENERATION_PHASE,
68+
false,
69+
false
70+
);
71+
72+
// create our manifest file here
73+
$testManifest = TestManifestFactory::makeManifest($config, []);
74+
TestGenerator::getInstance(null, []);
75+
if (empty($tests)) {
76+
SuiteGenerator::getInstance();
77+
}
78+
79+
$allActionGroups = ActionGroupObjectHandler::getInstance()->getAllObjects();
80+
81+
DocGenerator::getInstance()->createDocumentation($allActionGroups, $config, $clean);
82+
83+
$output->writeln("Generate Docs Command Run");
84+
}
85+
}

src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@ class ActionGroupObject
6464
*/
6565
private $arguments;
6666

67+
/**
68+
* An array used to store annotation information to values
69+
*
70+
* @var array
71+
*/
72+
private $annotations;
73+
74+
/**
75+
* An array used to store a list of filenames the action group is created by
76+
*
77+
* @var array
78+
*/
79+
private $filenames = [];
80+
6781
/**
6882
* String of parent Action Group
6983
*
@@ -75,21 +89,28 @@ class ActionGroupObject
7589
* ActionGroupObject constructor.
7690
*
7791
* @param string $name
92+
* @param array $annotations
7893
* @param ArgumentObject[] $arguments
7994
* @param array $actions
8095
* @param string $parentActionGroup
96+
* @param string $filename
8197
*/
82-
public function __construct($name, $arguments, $actions, $parentActionGroup)
98+
public function __construct($name, $annotations, $arguments, $actions, $parentActionGroup, $filename)
8399
{
84100
$this->varAttributes = array_merge(
85101
ActionObject::SELECTOR_ENABLED_ATTRIBUTES,
86102
ActionObject::DATA_ENABLED_ATTRIBUTES
87103
);
88104
$this->varAttributes[] = ActionObject::ACTION_ATTRIBUTE_URL;
89105
$this->name = $name;
106+
$this->annotations = $annotations;
90107
$this->arguments = $arguments;
91108
$this->parsedActions = $actions;
92109
$this->parentActionGroup = $parentActionGroup;
110+
$this->filenames = array_merge(
111+
$this->filenames,
112+
[$filename]
113+
);
93114
}
94115

95116
/**
@@ -439,6 +460,26 @@ public function getArguments()
439460
return $this->arguments;
440461
}
441462

463+
/**
464+
* Getter for the Action Group Annotations
465+
*
466+
* @return array
467+
*/
468+
public function getAnnotations()
469+
{
470+
return $this->annotations;
471+
}
472+
473+
/**
474+
* Getter for the Action Group File Names
475+
*
476+
* @return array
477+
*/
478+
public function getFileNames()
479+
{
480+
return $this->filenames;
481+
}
482+
442483
/**
443484
* Searches through ActionGroupObject's arguments and returns first argument wi
444485
* @param string $name
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\FunctionalTestingFramework\Test\Util;
8+
9+
use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig;
10+
use Magento\FunctionalTestingFramework\Exceptions\XmlException;
11+
use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil;
12+
13+
/**
14+
* Class AnnotationExtractor
15+
*/
16+
class ActionGroupAnnotationExtractor extends AnnotationExtractor
17+
{
18+
const ACTION_GROUP_REQUIRED_ANNOTATIONS = [
19+
"description",
20+
"page",
21+
];
22+
23+
/**
24+
* This method trims away irrelevant tags and returns annotations used in the array passed. The annotations
25+
* can be found in both Tests and their child element tests.
26+
*
27+
* @param array $testAnnotations
28+
* @param string $filename
29+
* @return array
30+
* @throws XmlException
31+
*/
32+
public function extractAnnotations($testAnnotations, $filename)
33+
{
34+
$annotationObjects = [];
35+
$annotations = $this->stripDescriptorTags($testAnnotations, parent::NODE_NAME);
36+
37+
// parse the Test annotations
38+
39+
foreach ($annotations as $annotationKey => $annotationData) {
40+
$annotationObjects[$annotationKey] = $annotationData[parent::ANNOTATION_VALUE];
41+
}
42+
43+
$this->validateMissingAnnotations($annotationObjects, $filename);
44+
return $annotationObjects;
45+
}
46+
47+
/**
48+
* Validates given annotations against list of required annotations.
49+
* @param array $annotationObjects
50+
* @return void
51+
*/
52+
private function validateMissingAnnotations($annotationObjects, $filename)
53+
{
54+
$missingAnnotations = [];
55+
56+
foreach (self::ACTION_GROUP_REQUIRED_ANNOTATIONS as $REQUIRED_ANNOTATION) {
57+
if (!array_key_exists($REQUIRED_ANNOTATION, $annotationObjects)) {
58+
$missingAnnotations[] = $REQUIRED_ANNOTATION;
59+
}
60+
}
61+
62+
if (!empty($missingAnnotations)) {
63+
$message = "Action Group File {$filename} is missing required annotations.";
64+
LoggingUtil::getInstance()->getLogger(ActionObject::class)->deprecation(
65+
$message,
66+
["actionGroup" => $filename, "missingAnnotations" => implode(", ", $missingAnnotations)]
67+
);
68+
}
69+
}
70+
}

src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class ActionGroupObjectExtractor extends BaseObjectExtractor
1818
{
1919
const DEFAULT_VALUE = 'defaultValue';
2020
const ACTION_GROUP_ARGUMENTS = 'arguments';
21+
const ACTION_GROUP_ANNOTATIONS = 'annotations';
2122
const FILENAME = 'filename';
2223
const ACTION_GROUP_INSERT_BEFORE = "insertBefore";
2324
const ACTION_GROUP_INSERT_AFTER = "insertAfter";
@@ -30,12 +31,20 @@ class ActionGroupObjectExtractor extends BaseObjectExtractor
3031
*/
3132
private $actionObjectExtractor;
3233

34+
/**
35+
* Annotation Extractor object
36+
*
37+
* @var AnnotationExtractor
38+
*/
39+
private $annotationExtractor;
40+
3341
/**
3442
* ActionGroupObjectExtractor constructor.
3543
*/
3644
public function __construct()
3745
{
3846
$this->actionObjectExtractor = new ActionObjectExtractor();
47+
$this->annotationExtractor = new ActionGroupAnnotationExtractor();
3948
}
4049

4150
/**
@@ -55,13 +64,24 @@ public function extractActionGroup($actionGroupData)
5564
self::NODE_NAME,
5665
self::ACTION_GROUP_ARGUMENTS,
5766
self::NAME,
67+
self::ACTION_GROUP_ANNOTATIONS,
5868
self::FILENAME,
5969
self::ACTION_GROUP_INSERT_BEFORE,
6070
self::ACTION_GROUP_INSERT_AFTER,
6171
self::EXTENDS_ACTION_GROUP
6272
);
6373

6474
// TODO filename is now available to the ActionGroupObject, integrate this into debug and error statements
75+
76+
try {
77+
$annotations = $this->annotationExtractor->extractAnnotations(
78+
$actionGroupData[self::ACTION_GROUP_ANNOTATIONS] ?? [],
79+
$actionGroupData[self::FILENAME]
80+
);
81+
} catch (\Exception $error) {
82+
throw new XmlException($error->getMessage() . " in Action Group " . $actionGroupData[self::FILENAME]);
83+
}
84+
6585
try {
6686
$actions = $this->actionObjectExtractor->extractActions($actionData);
6787
} catch (\Exception $error) {
@@ -74,9 +94,11 @@ public function extractActionGroup($actionGroupData)
7494

7595
return new ActionGroupObject(
7696
$actionGroupData[self::NAME],
97+
$annotations,
7798
$arguments,
7899
$actions,
79-
$actionGroupReference
100+
$actionGroupReference,
101+
$actionGroupData[self::FILENAME]
80102
);
81103
}
82104

src/Magento/FunctionalTestingFramework/Test/Util/ObjectExtensionUtil.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,11 @@ public function extendActionGroup($actionGroupObject)
129129
// Create new Action Group object to return
130130
$extendedActionGroup = new ActionGroupObject(
131131
$actionGroupObject->getName(),
132+
$actionGroupObject->getAnnotations(),
132133
$extendedArguments,
133134
$newActions,
134-
$actionGroupObject->getParentName()
135+
$actionGroupObject->getParentName(),
136+
$actionGroupObject->getFileNames()
135137
);
136138
return $extendedActionGroup;
137139
}

src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@
3030
</xs:sequence>
3131
</xs:complexType>
3232
</xs:element>
33+
<xs:element name="annotations">
34+
<xs:complexType>
35+
<xs:sequence>
36+
<xs:element name="description"/>
37+
<xs:element name="page"/>
38+
</xs:sequence>
39+
</xs:complexType>
40+
</xs:element>
3341
</xs:choice>
3442
<xs:attribute type="xs:string" name="name" use="required"/>
3543
<xs:attribute type="xs:string" name="filename"/>

0 commit comments

Comments
 (0)