Skip to content

Commit 22a1ef1

Browse files
authored
MQE-992: Allow Tests and Action Groups to use inheritance (magento#128)
* MQE-992: Allow Tests and Action Groups to use inheritance - Added Test Inheritance * MQE-992: Allow Tests and Action Groups to use inheritance - Added Action Group and moved inheritance to getObject calls in the handlers - Added index to actions - Updated unit test appropriately * MQE-992: Allow Tests and Action Groups to use inheritance - Fixed docstrings and use(s) - Moved some functionality for extending groups * MQE-992: Allow Tests and Action Groups to use inheritance - Added Verification Tests - Added Hooks to Test Extension - Updated a docstring for hook array * MQE-992: Allow Tests and Action Groups to use inheritance - Added ObjectExtension Unit Tests - Updated ArrayBuilders * MQE-992: Allow Tests and Action Groups to use inheritance - Added unit tests - Updated and split out verification tests - Updated docstrings - Added method for getting raw parsed steps to Test Object - Added Comments to ObjectExtension * MQE-992: Allow Tests and Action Groups to use inheritance - Updated class variable docstring - Removed unused verification resource - Added capture for output string for unit test * MQE-992: Allow Tests and Action Groups to use inheritance - Changed ObjectExtionsion to add Util - Added Constructor and updated methods to non-static - updated indexes * MQE-992: Allow Tests and Action Groups to use inheritance - Added support for Remove actions - Added more verification and unit tests - Refactored one long function * MQE-992: Allow Tests and Action Groups to use inheritance - Cleaned up remove function - Removed throw - Set stepKey differently for remove type actions * MQE-992: Allow Tests and Action Groups to use inheritance - Removed commentd line - moved creation of ObjectExtension object to class property * MQE-992: Allow Tests and Action Groups to use inheritance Moved stepKey assignment to Flat * MQE-992: Allow Tests and Action Groups to use inheritance - Removed unused constant * MQE-992: Allow Tests and Action Groups to use inheritance - Added functionality for removing actions from within test hooks * MQE-992: Allow Tests and Action Groups to use inheritance - Made change to order for actions in action groups when resolving actions * MQE-992: Allow Tests and Action Groups to use inheritance - Updated test for merged code * MQE-992: Allow Tests and Action Groups to use inheritance - Added warning instead of exception for non-existent parent tests * MQE-992: Allow Tests and Action Groups to use inheritance - Updated to only add skip to groups if it doesn't already exist * MQE-992: Allow Tests and Action Groups to use inheritance - Moved skipTest function to Object Extension Util
1 parent 1bedd14 commit 22a1ef1

32 files changed

+1692
-23
lines changed

dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,12 @@ public function testGetTestObject()
6666
$expectedBeforeHookObject = new TestHookObject(
6767
TestObjectExtractor::TEST_BEFORE_HOOK,
6868
$testDataArrayBuilder->testName,
69-
[$expectedBeforeActionObject]
69+
["testActionBefore" => $expectedBeforeActionObject]
7070
);
7171
$expectedAfterHookObject = new TestHookObject(
7272
TestObjectExtractor::TEST_AFTER_HOOK,
7373
$testDataArrayBuilder->testName,
74-
[$expectedAfterActionObject]
74+
["testActionAfter" => $expectedAfterActionObject]
7575
);
7676
$expectedFailedHookObject = new TestHookObject(
7777
TestObjectExtractor::TEST_FAILED_HOOK,
@@ -86,7 +86,7 @@ public function testGetTestObject()
8686
);
8787
$expectedTestObject = new TestObject(
8888
$testDataArrayBuilder->testName,
89-
[$expectedTestActionObject],
89+
["testActionInTest" => $expectedTestActionObject],
9090
[
9191
'features' => ['NO MODULE DETECTED'],
9292
'group' => ['test']
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace tests\unit\Magento\FunctionalTestFramework\Test\Util;
7+
8+
use AspectMock\Test as AspectMock;
9+
use Magento\FunctionalTestingFramework\ObjectManager\ObjectManager;
10+
use Magento\FunctionalTestingFramework\ObjectManagerFactory;
11+
use Magento\FunctionalTestingFramework\Test\Handlers\ActionGroupObjectHandler;
12+
use Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler;
13+
use Magento\FunctionalTestingFramework\Test\Parsers\ActionGroupDataParser;
14+
use Magento\FunctionalTestingFramework\Test\Parsers\TestDataParser;
15+
use PHPUnit\Framework\TestCase;
16+
use tests\unit\Util\TestDataArrayBuilder;
17+
18+
class ObjectExtensionUtilTest extends TestCase
19+
{
20+
/**
21+
* Tests generating a test that extends another test
22+
* @throws \Exception
23+
*/
24+
public function testGenerateExtendedTest()
25+
{
26+
$mockActions = [
27+
"mockStep" => ["nodeName" => "mockNode", "stepKey" => "mockStep"]
28+
];
29+
30+
$testDataArrayBuilder = new TestDataArrayBuilder();
31+
$mockSimpleTest = $testDataArrayBuilder
32+
->withName('simpleTest')
33+
->withTestActions($mockActions)
34+
->build();
35+
36+
$mockExtendedTest = $testDataArrayBuilder
37+
->withName('extendedTest')
38+
->withTestReference("simpleTest")
39+
->build();
40+
41+
$mockTestData = ['tests' => array_merge($mockSimpleTest, $mockExtendedTest)];
42+
$this->setMockTestOutput($mockTestData);
43+
44+
$this->expectOutputString("Extending Test: simpleTest => extendedTest" . PHP_EOL);
45+
46+
// parse and generate test object with mocked data
47+
$testObject = TestObjectHandler::getInstance()->getObject('extendedTest');
48+
49+
// assert that expected test is generated
50+
$this->assertEquals($testObject->getParentName(), "simpleTest");
51+
$this->assertArrayHasKey("mockStep", $testObject->getOrderedActions());
52+
}
53+
54+
/**
55+
* Tests generating a test that extends another test
56+
* @throws \Exception
57+
*/
58+
public function testGenerateExtendedWithHooks()
59+
{
60+
$mockBeforeHooks = [
61+
"beforeHookAction" => ["nodeName" => "mockNodeBefore", "stepKey" => "mockStepBefore"]
62+
];
63+
$mockAfterHooks = [
64+
"afterHookAction" => ["nodeName" => "mockNodeAfter", "stepKey" => "mockStepAfter"]
65+
];
66+
67+
$testDataArrayBuilder = new TestDataArrayBuilder();
68+
$mockSimpleTest = $testDataArrayBuilder
69+
->withName('simpleTest')
70+
->withBeforeHook($mockBeforeHooks)
71+
->withAfterHook($mockAfterHooks)
72+
->build();
73+
74+
$mockExtendedTest = $testDataArrayBuilder
75+
->withName('extendedTest')
76+
->withTestReference("simpleTest")
77+
->build();
78+
79+
$mockTestData = ['tests' => array_merge($mockSimpleTest, $mockExtendedTest)];
80+
$this->setMockTestOutput($mockTestData);
81+
82+
$this->expectOutputString("Extending Test: simpleTest => extendedTest" . PHP_EOL);
83+
84+
// parse and generate test object with mocked data
85+
$testObject = TestObjectHandler::getInstance()->getObject('extendedTest');
86+
87+
// assert that expected test is generated
88+
$this->assertEquals($testObject->getParentName(), "simpleTest");
89+
$this->assertArrayHasKey("mockStepBefore", $testObject->getHooks()['before']->getActions());
90+
$this->assertArrayHasKey("mockStepAfter", $testObject->getHooks()['after']->getActions());
91+
}
92+
93+
/**
94+
* Tests generating a test that extends another test
95+
* @throws \Exception
96+
*/
97+
public function testExtendedTestNoParent()
98+
{
99+
$testDataArrayBuilder = new TestDataArrayBuilder();
100+
$mockExtendedTest = $testDataArrayBuilder
101+
->withName('extendedTest')
102+
->withTestReference("simpleTest")
103+
->build();
104+
105+
$mockTestData = ['tests' => array_merge($mockExtendedTest)];
106+
$this->setMockTestOutput($mockTestData);
107+
108+
$this->expectOutputString("Parent Test simpleTest not defined for Test extendedTest. Skipping Test." . PHP_EOL);
109+
110+
// parse and generate test object with mocked data
111+
TestObjectHandler::getInstance()->getObject('extendedTest');
112+
}
113+
114+
/**
115+
* Tests generating a test that extends another test
116+
* @throws \Exception
117+
*/
118+
public function testExtendingExtendedTest()
119+
{
120+
$testDataArrayBuilder = new TestDataArrayBuilder();
121+
$mockParentTest = $testDataArrayBuilder
122+
->withName('anotherTest')
123+
->withTestActions()
124+
->build();
125+
126+
$mockSimpleTest = $testDataArrayBuilder
127+
->withName('simpleTest')
128+
->withTestActions()
129+
->withTestReference("anotherTest")
130+
->build();
131+
132+
$mockExtendedTest = $testDataArrayBuilder
133+
->withName('extendedTest')
134+
->withTestReference("simpleTest")
135+
->build();
136+
137+
$mockTestData = ['tests' => array_merge($mockParentTest, $mockSimpleTest, $mockExtendedTest)];
138+
$this->setMockTestOutput($mockTestData);
139+
140+
$this->expectOutputString("Extending Test: anotherTest => simpleTest" . PHP_EOL);
141+
$this->expectExceptionMessage("Cannot extend a test that already extends another test. Test: simpleTest");
142+
143+
// parse and generate test object with mocked data
144+
TestObjectHandler::getInstance()->getObject('extendedTest');
145+
}
146+
147+
/**
148+
* Tests generating an action group that extends another action group
149+
* @throws \Exception
150+
*/
151+
public function testGenerateExtendedActionGroup()
152+
{
153+
$mockSimpleActionGroup = [
154+
"nodeName" => "actionGroup",
155+
"name" => "mockSimpleActionGroup",
156+
"filename" => "someFile",
157+
"commentHere" => [
158+
"nodeName" => "comment",
159+
"selector" => "selector",
160+
"stepKey" => "commentHere"
161+
],
162+
"parentComment" => [
163+
"nodeName" => "comment",
164+
"selector" => "parentSelector",
165+
"stepKey" => "parentComment"
166+
],
167+
];
168+
169+
$mockExtendedActionGroup = [
170+
"nodeName" => "actionGroup",
171+
"name" => "mockExtendedActionGroup",
172+
"filename" => "someFile",
173+
"extends" => "mockSimpleActionGroup",
174+
"commentHere" => [
175+
"nodeName" => "comment",
176+
"selector" => "otherSelector",
177+
"stepKey" => "commentHere"
178+
],
179+
];
180+
181+
$mockActionGroupData = [
182+
'actionGroups' => [
183+
'mockSimpleActionGroup' => $mockSimpleActionGroup,
184+
'mockExtendedActionGroup' => $mockExtendedActionGroup
185+
]
186+
];
187+
$this->setMockTestOutput(null, $mockActionGroupData);
188+
189+
$this->expectOutputString("Extending Action Group: mockSimpleActionGroup => mockExtendedActionGroup" . PHP_EOL);
190+
191+
// parse and generate test object with mocked data
192+
$actionGroupObject = ActionGroupObjectHandler::getInstance()->getObject('mockExtendedActionGroup');
193+
194+
// assert that expected test is generated
195+
$this->assertEquals("mockSimpleActionGroup", $actionGroupObject->getParentName());
196+
$actions = $actionGroupObject->getActions();
197+
$this->assertEquals("otherSelector", $actions["commentHere"]->getCustomActionAttributes()["selector"]);
198+
$this->assertEquals("parentSelector", $actions["parentComment"]->getCustomActionAttributes()["selector"]);
199+
}
200+
201+
/**
202+
* Tests generating an action group that extends an action group that does not exist
203+
* @throws \Exception
204+
*/
205+
public function testGenerateExtendedActionGroupNoParent()
206+
{
207+
$mockExtendedActionGroup = [
208+
"nodeName" => "actionGroup",
209+
"name" => "mockSimpleActionGroup",
210+
"filename" => "someFile",
211+
"extends" => "mockSimpleActionGroup",
212+
"commentHere" => [
213+
"nodeName" => "comment",
214+
"selector" => "otherSelector",
215+
"stepKey" => "commentHere"
216+
],
217+
];
218+
219+
$mockActionGroupData = [
220+
'actionGroups' => [
221+
'mockExtendedActionGroup' => $mockExtendedActionGroup
222+
]
223+
];
224+
$this->setMockTestOutput(null, $mockActionGroupData);
225+
226+
$this->expectExceptionMessage(
227+
"Parent Action Group mockSimpleActionGroup not defined for Test " . $mockExtendedActionGroup['extends']
228+
);
229+
230+
// parse and generate test object with mocked data
231+
ActionGroupObjectHandler::getInstance()->getObject('mockExtendedActionGroup');
232+
}
233+
234+
/**
235+
* Tests generating an action group that extends another action group that is already extended
236+
* @throws \Exception
237+
*/
238+
public function testExtendingExtendedActionGroup()
239+
{
240+
$mockParentActionGroup = [
241+
"nodeName" => "actionGroup",
242+
"name" => "mockParentActionGroup",
243+
"filename" => "someFile"
244+
];
245+
246+
$mockSimpleActionGroup = [
247+
"nodeName" => "actionGroup",
248+
"name" => "mockSimpleActionGroup",
249+
"filename" => "someFile",
250+
"extends" => "mockParentActionGroup",
251+
];
252+
253+
$mockExtendedActionGroup = [
254+
"nodeName" => "actionGroup",
255+
"name" => "mockSimpleActionGroup",
256+
"filename" => "someFile",
257+
"extends" => "mockSimpleActionGroup",
258+
];
259+
260+
$mockActionGroupData = [
261+
'actionGroups' => [
262+
'mockParentActionGroup' => $mockParentActionGroup,
263+
'mockSimpleActionGroup' => $mockSimpleActionGroup,
264+
'mockExtendedActionGroup' => $mockExtendedActionGroup
265+
]
266+
];
267+
$this->setMockTestOutput(null, $mockActionGroupData);
268+
269+
$this->expectOutputString("Extending Action Group: mockParentActionGroup => mockSimpleActionGroup" . PHP_EOL);
270+
$this->expectExceptionMessage(
271+
"Cannot extend an action group that already extends another action group. " . $mockSimpleActionGroup['name']
272+
);
273+
274+
// parse and generate test object with mocked data
275+
ActionGroupObjectHandler::getInstance()->getObject('mockExtendedActionGroup');
276+
}
277+
278+
/**
279+
* Function used to set mock for parser return and force init method to run between tests.
280+
*
281+
* @param array $testData
282+
* @throws \Exception
283+
*/
284+
private function setMockTestOutput($testData = null, $actionGroupData = null)
285+
{
286+
// clear test object handler value to inject parsed content
287+
$property = new \ReflectionProperty(TestObjectHandler::class, 'testObjectHandler');
288+
$property->setAccessible(true);
289+
$property->setValue(null);
290+
291+
// clear test object handler value to inject parsed content
292+
$property = new \ReflectionProperty(ActionGroupObjectHandler::class, 'ACTION_GROUP_OBJECT_HANDLER');
293+
$property->setAccessible(true);
294+
$property->setValue(null);
295+
296+
$mockDataParser = AspectMock::double(TestDataParser::class, ['readTestData' => $testData])->make();
297+
$mockActionGroupParser = AspectMock::double(
298+
ActionGroupDataParser::class,
299+
['readActionGroupData' => $actionGroupData]
300+
)->make();
301+
$instance = AspectMock::double(
302+
ObjectManager::class,
303+
['create' => function ($clazz) use (
304+
$mockDataParser,
305+
$mockActionGroupParser
306+
) {
307+
if ($clazz == TestDataParser::class) {
308+
return $mockDataParser;
309+
}
310+
if ($clazz == ActionGroupDataParser::class) {
311+
return $mockActionGroupParser;
312+
}
313+
}]
314+
)->make();
315+
// bypass the private constructor
316+
AspectMock::double(ObjectManagerFactory::class, ['getObjectManager' => $instance]);
317+
}
318+
}

dev/tests/unit/Util/ActionGroupObjectBuilder.php

+21-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ class ActionGroupObjectBuilder
3434
*/
3535
private $arguments = [];
3636

37+
/**
38+
* Action Group Object Builder default name
39+
*
40+
* @var string
41+
*/
42+
private $extends = null;
43+
3744
/**
3845
* Setter for the Action Group Object name
3946
*
@@ -70,6 +77,18 @@ public function withActionObjects($actionObjs)
7077
return $this;
7178
}
7279

80+
/**
81+
* Setter for the Action Group Object extended objects
82+
*
83+
* @param string $extendedActionGroup
84+
* @return ActionGroupObjectBuilder
85+
*/
86+
public function withExtendedAction($extendedActionGroup)
87+
{
88+
$this->extends = $extendedActionGroup;
89+
return $this;
90+
}
91+
7392
/**
7493
* ActionGroupObjectBuilder constructor.
7594
*/
@@ -90,7 +109,8 @@ public function build()
90109
return new ActionGroupObject(
91110
$this->name,
92111
$this->arguments,
93-
$this->actionObjects
112+
$this->actionObjects,
113+
$this->extends
94114
);
95115
}
96116
}

0 commit comments

Comments
 (0)