Skip to content

Commit 7b53949

Browse files
committed
MQE-2158: support using actions from multiple modules in Suites
1 parent fc05c77 commit 7b53949

File tree

7 files changed

+410
-53
lines changed

7 files changed

+410
-53
lines changed

dev/tests/verification/Resources/functionalSuiteHooks.txt

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ use Facebook\WebDriver\Remote\RemoteWebDriver;
66
use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler;
77
use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore;
88
use Magento\FunctionalTestingFramework\Module\MagentoWebDriver;
9+
use Magento\FunctionalTestingFramework\Module\MagentoAssert;
10+
use Magento\FunctionalTestingFramework\Module\MagentoActionProxies;
11+
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
12+
use Codeception\Lib\ModuleContainer;
13+
use Codeception\Module;
914

1015
/**
1116
* Group class is Codeception Extension which is allowed to handle to all internal events.
@@ -24,9 +29,15 @@ class functionalSuiteHooks extends \Codeception\GroupObject
2429
private $currentTestRun = 0;
2530
private static $HOOK_EXECUTION_INIT = "\n/******** Beginning execution of functionalSuiteHooks suite %s block ********/\n";
2631
private static $HOOK_EXECUTION_END = "\n/******** Execution of functionalSuiteHooks suite %s block complete ********/\n";
32+
/** @var MagentoWebDriver */
33+
private $webDriver;
34+
/** @var ModuleContainer */
35+
private $moduleContainer;
2736

2837
public function _before(\Codeception\Event\TestEvent $e)
2938
{
39+
$this->webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver');
40+
$this->moduleContainer = $this->webDriver->getModuleContainer();
3041
// increment test count per execution
3142
$this->currentTestRun++;
3243
$this->executePreConditions();
@@ -37,22 +48,18 @@ class functionalSuiteHooks extends \Codeception\GroupObject
3748
}
3849
}
3950

40-
4151
private function executePreConditions()
4252
{
4353
if ($this->currentTestRun == 1) {
4454
print sprintf(self::$HOOK_EXECUTION_INIT, "before");
4555

46-
/** @var MagentoWebDriver $webDriver */
47-
$webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver');
48-
4956
try {
50-
if ($webDriver->webDriver != null) {
51-
$webDriver->_restart();
57+
if ($this->webDriver->webDriver != null) {
58+
$this->webDriver->_restart();
5259
} else {
53-
$webDriver->_initializeSession();
60+
$this->webDriver->_initializeSession();
5461
}
55-
$webDriver->amOnPage("some.url"); // stepKey: before
62+
$this->getModuleForAction("amOnPage")->amOnPage("some.url"); // stepKey: before
5663
$createOneFields['someKey'] = "dataHere";
5764
PersistedObjectHandler::getInstance()->createEntity(
5865
"createOne",
@@ -79,18 +86,18 @@ class functionalSuiteHooks extends \Codeception\GroupObject
7986
"createEntityFour",
8087
["createEntityTwo", "createEntityThree"]
8188
);
82-
$webDriver->click(PersistedObjectHandler::getInstance()->retrieveEntityField('createTwo', 'data', 'suite')); // stepKey: clickWithData
89+
$this->getModuleForAction("click")->click(PersistedObjectHandler::getInstance()->retrieveEntityField('createTwo', 'data', 'suite')); // stepKey: clickWithData
8390
print("Entering Action Group [AC] actionGroupWithTwoArguments");
84-
$webDriver->see("John", msq("uniqueData") . "John"); // stepKey: seeFirstNameAC
91+
$this->getModuleForAction("see")->see("John", msq("uniqueData") . "John"); // stepKey: seeFirstNameAC
8592
print("Exiting Action Group [AC] actionGroupWithTwoArguments");
8693
} catch (\Exception $exception) {
8794
$this->preconditionFailure = $exception->getMessage();
8895
}
8996

9097
// reset configuration and close session
91-
$webDriver->_resetConfig();
92-
$webDriver->webDriver->close();
93-
$webDriver->webDriver = null;
98+
$this->webDriver->_resetConfig();
99+
$this->webDriver->webDriver->close();
100+
$this->webDriver->webDriver = null;
94101

95102
print sprintf(self::$HOOK_EXECUTION_END, "before");
96103
}
@@ -101,15 +108,11 @@ class functionalSuiteHooks extends \Codeception\GroupObject
101108
$this->executePostConditions($e);
102109
}
103110

104-
105111
private function executePostConditions(\Codeception\Event\TestEvent $e)
106112
{
107113
if ($this->currentTestRun == $this->testCount) {
108114
print sprintf(self::$HOOK_EXECUTION_INIT, "after");
109115

110-
/** @var MagentoWebDriver $webDriver */
111-
$webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver');
112-
113116
try {
114117
// Find out if Test in Suite failed, will cause potential failures in suite after
115118
$cest = $e->getTest();
@@ -132,23 +135,23 @@ class functionalSuiteHooks extends \Codeception\GroupObject
132135
}
133136
}
134137
}
135-
if ($webDriver->webDriver != null) {
136-
$webDriver->_restart();
138+
if ($this->webDriver->webDriver != null) {
139+
$this->webDriver->_restart();
137140
} else {
138-
$webDriver->_initializeSession();
141+
$this->webDriver->_initializeSession();
139142
}
140-
$webDriver->amOnPage("some.url"); // stepKey: after
141-
$webDriver->deleteEntityByUrl("deleteThis"); // stepKey: delete
143+
$this->getModuleForAction("amOnPage")->amOnPage("some.url"); // stepKey: after
144+
$this->getModuleForAction("deleteEntityByUrl")->deleteEntityByUrl("deleteThis"); // stepKey: delete
142145
print("Entering Action Group [AC] actionGroupWithTwoArguments");
143-
$webDriver->see("John", msq("uniqueData") . "John"); // stepKey: seeFirstNameAC
146+
$this->getModuleForAction("see")->see("John", msq("uniqueData") . "John"); // stepKey: seeFirstNameAC
144147
print("Exiting Action Group [AC] actionGroupWithTwoArguments");
145148
} catch (\Exception $exception) {
146149
print $exception->getMessage();
147150
}
148151

149152
PersistedObjectHandler::getInstance()->clearSuiteObjects();
150153

151-
$this->closeSession($webDriver);
154+
$this->closeSession($this->webDriver);
152155

153156
print sprintf(self::$HOOK_EXECUTION_END, "after");
154157
}
@@ -158,13 +161,12 @@ class functionalSuiteHooks extends \Codeception\GroupObject
158161
* Close session method closes current session.
159162
* If config 'close_all_sessions' is set to 'true' all sessions will be closed.
160163
*
161-
* @param MagentoWebDriver $webDriver
162164
* return void
163165
*/
164-
private function closeSession(MagentoWebDriver $webDriver): void
166+
private function closeSession(): void
165167
{
166-
$webDriverConfig = $webDriver->_getConfig();
167-
$webDriver->_closeSession();
168+
$webDriverConfig = $this->webDriver->_getConfig();
169+
$this->webDriver->_closeSession();
168170
if (isset($webDriverConfig['close_all_sessions']) && $webDriverConfig['close_all_sessions'] === "true") {
169171
$wdHost = sprintf(
170172
'%s://%s:%s%s',
@@ -180,4 +182,20 @@ class functionalSuiteHooks extends \Codeception\GroupObject
180182
}
181183
}
182184
}
185+
186+
/**
187+
* Return the module for an action.
188+
*
189+
* @param string $action
190+
* @return Module
191+
* @throws \Exception
192+
*/
193+
private function getModuleForAction($action)
194+
{
195+
$module = $this->moduleContainer->moduleForAction($action);
196+
if ($module === null) {
197+
throw new TestFrameworkException('Invalid action "' . $action . '"' . PHP_EOL);
198+
}
199+
return $module;
200+
}
183201
}
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
<?php
2+
3+
namespace Group;
4+
5+
use Facebook\WebDriver\Remote\RemoteWebDriver;
6+
use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler;
7+
use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore;
8+
use Magento\FunctionalTestingFramework\Module\MagentoWebDriver;
9+
use Magento\FunctionalTestingFramework\Module\MagentoAssert;
10+
use Magento\FunctionalTestingFramework\Module\MagentoActionProxies;
11+
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
12+
use Codeception\Lib\ModuleContainer;
13+
use Codeception\Module;
14+
15+
/**
16+
* Group class is Codeception Extension which is allowed to handle to all internal events.
17+
* This class itself can be used to listen events for test execution of one particular group.
18+
* It may be especially useful to create fixtures data, prepare server, etc.
19+
*
20+
* INSTALLATION:
21+
*
22+
* To use this group extension, include it to "extensions" option of global Codeception config.
23+
*/
24+
class functionalSuiteUsingSecretData extends \Codeception\GroupObject
25+
{
26+
public static $group = 'functionalSuiteUsingSecretData';
27+
private $testCount = 1;
28+
private $preconditionFailure = null;
29+
private $currentTestRun = 0;
30+
private static $HOOK_EXECUTION_INIT = "\n/******** Beginning execution of functionalSuiteUsingSecretData suite %s block ********/\n";
31+
private static $HOOK_EXECUTION_END = "\n/******** Execution of functionalSuiteUsingSecretData suite %s block complete ********/\n";
32+
/** @var MagentoWebDriver */
33+
private $webDriver;
34+
/** @var ModuleContainer */
35+
private $moduleContainer;
36+
37+
public function _before(\Codeception\Event\TestEvent $e)
38+
{
39+
$this->webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver');
40+
$this->moduleContainer = $this->webDriver->getModuleContainer();
41+
// increment test count per execution
42+
$this->currentTestRun++;
43+
$this->executePreConditions();
44+
45+
if ($this->preconditionFailure != null) {
46+
//if our preconditions fail, we need to mark all the tests as incomplete.
47+
$e->getTest()->getMetadata()->setIncomplete("SUITE PRECONDITION FAILED:" . PHP_EOL . $this->preconditionFailure);
48+
}
49+
}
50+
51+
private function executePreConditions()
52+
{
53+
if ($this->currentTestRun == 1) {
54+
print sprintf(self::$HOOK_EXECUTION_INIT, "before");
55+
56+
try {
57+
if ($this->webDriver->webDriver != null) {
58+
$this->webDriver->_restart();
59+
} else {
60+
$this->webDriver->_initializeSession();
61+
}
62+
$cli = $this->getModuleForAction("magentoCLISecret")->magentoCLISecret($this->getModuleForAction("getSecret")->getSecret("magento/some/secret"), 60); // stepKey: cli
63+
print($cli); // stepKey: cli
64+
$create1Fields['someKey'] = "dataHere";
65+
PersistedObjectHandler::getInstance()->createEntity(
66+
"create1",
67+
"suite",
68+
"SecretData",
69+
[],
70+
$create1Fields
71+
);
72+
PersistedObjectHandler::getInstance()->createEntity(
73+
"create2",
74+
"suite",
75+
"SecretData",
76+
[]
77+
);
78+
PersistedObjectHandler::getInstance()->createEntity(
79+
"create3",
80+
"suite",
81+
"SecretData",
82+
["create1", "create2"]
83+
);
84+
$this->getModuleForAction("fillSecretField")->fillSecretField("#fill", $this->getModuleForAction("getSecret")->getSecret("magento/some/secret") . "+" . $this->getModuleForAction("getSecret")->getSecret("magento/some/secret")); // stepKey: fillBefore
85+
$this->getModuleForAction("click")->click(PersistedObjectHandler::getInstance()->retrieveEntityField('create2', 'key2', 'suite')); // stepKey: click
86+
} catch (\Exception $exception) {
87+
$this->preconditionFailure = $exception->getMessage();
88+
}
89+
90+
// reset configuration and close session
91+
$this->webDriver->_resetConfig();
92+
$this->webDriver->webDriver->close();
93+
$this->webDriver->webDriver = null;
94+
95+
print sprintf(self::$HOOK_EXECUTION_END, "before");
96+
}
97+
}
98+
99+
public function _after(\Codeception\Event\TestEvent $e)
100+
{
101+
$this->executePostConditions($e);
102+
}
103+
104+
private function executePostConditions(\Codeception\Event\TestEvent $e)
105+
{
106+
if ($this->currentTestRun == $this->testCount) {
107+
print sprintf(self::$HOOK_EXECUTION_INIT, "after");
108+
109+
try {
110+
// Find out if Test in Suite failed, will cause potential failures in suite after
111+
$cest = $e->getTest();
112+
113+
//Access private TestResultObject to find stack and if there are any errors (as opposed to failures)
114+
$testResultObject = call_user_func(\Closure::bind(
115+
function () use ($cest) {
116+
return $cest->getTestResultObject();
117+
},
118+
$cest
119+
));
120+
$errors = $testResultObject->errors();
121+
122+
if (!empty($errors)) {
123+
foreach ($errors as $error) {
124+
if ($error->failedTest()->getTestMethod() == $cest->getName()) {
125+
// Do not attempt to run _after if failure was in the _after block
126+
// Try to run _after but catch exceptions to prevent them from overwriting original failure.
127+
print("LAST TEST IN SUITE FAILED, TEST AFTER MAY NOT BE SUCCESSFUL\n");
128+
}
129+
}
130+
}
131+
if ($this->webDriver->webDriver != null) {
132+
$this->webDriver->_restart();
133+
} else {
134+
$this->webDriver->_initializeSession();
135+
}
136+
PersistedObjectHandler::getInstance()->deleteEntity(
137+
"create1",
138+
"suite"
139+
);
140+
PersistedObjectHandler::getInstance()->deleteEntity(
141+
"create2",
142+
"suite"
143+
);
144+
PersistedObjectHandler::getInstance()->deleteEntity(
145+
"create3",
146+
"suite"
147+
);
148+
$this->getModuleForAction("deleteEntityByUrl")->deleteEntityByUrl("deleteThis"); // stepKey: deleteThis
149+
$this->getModuleForAction("fillSecretField")->fillSecretField("#fill", $this->getModuleForAction("getSecret")->getSecret("magento/some/secret")); // stepKey: fillAfter
150+
$cli2 = $this->getModuleForAction("magentoCLISecret")->magentoCLISecret($this->getModuleForAction("getSecret")->getSecret("magento/some/secret") . "-some/data-" . $this->getModuleForAction("getSecret")->getSecret("magento/some/secret"), 60); // stepKey: cli2
151+
print($cli2); // stepKey: cli2
152+
} catch (\Exception $exception) {
153+
print $exception->getMessage();
154+
}
155+
156+
PersistedObjectHandler::getInstance()->clearSuiteObjects();
157+
158+
$this->closeSession($this->webDriver);
159+
160+
print sprintf(self::$HOOK_EXECUTION_END, "after");
161+
}
162+
}
163+
164+
/**
165+
* Close session method closes current session.
166+
* If config 'close_all_sessions' is set to 'true' all sessions will be closed.
167+
*
168+
* return void
169+
*/
170+
private function closeSession(): void
171+
{
172+
$webDriverConfig = $this->webDriver->_getConfig();
173+
$this->webDriver->_closeSession();
174+
if (isset($webDriverConfig['close_all_sessions']) && $webDriverConfig['close_all_sessions'] === "true") {
175+
$wdHost = sprintf(
176+
'%s://%s:%s%s',
177+
$webDriverConfig['protocol'],
178+
$webDriverConfig['host'],
179+
$webDriverConfig['port'],
180+
$webDriverConfig['path']
181+
);
182+
$availableSessions = RemoteWebDriver::getAllSessions($wdHost);
183+
foreach ($availableSessions as $session) {
184+
$remoteWebDriver = RemoteWebDriver::createBySessionID($session['id'], $wdHost);
185+
$remoteWebDriver->quit();
186+
}
187+
}
188+
}
189+
190+
/**
191+
* Return the module for an action.
192+
*
193+
* @param string $action
194+
* @return Module
195+
* @throws \Exception
196+
*/
197+
private function getModuleForAction($action)
198+
{
199+
$module = $this->moduleContainer->moduleForAction($action);
200+
if ($module === null) {
201+
throw new TestFrameworkException('Invalid action "' . $action . '"' . PHP_EOL);
202+
}
203+
return $module;
204+
}
205+
}

0 commit comments

Comments
 (0)