Skip to content

Commit 2703d1d

Browse files
authored
Merge branch 'develop' into MQE-983
2 parents 2b92b62 + 40b85ab commit 2703d1d

33 files changed

+670
-61
lines changed

dev/tests/_bootstrap.php

+21
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,27 @@
6969
require($unitUtilFile);
7070
}
7171

72+
73+
// Mocks suite files location getter return to get files in verification/_suite Directory
74+
// This mocks the paths of the suite files but still parses the xml files
75+
$suiteDirectory = TESTS_BP . DIRECTORY_SEPARATOR . "verification" . DIRECTORY_SEPARATOR . "_suite";
76+
77+
$paths = [
78+
$suiteDirectory . DIRECTORY_SEPARATOR . 'functionalSuite.xml',
79+
$suiteDirectory . DIRECTORY_SEPARATOR . 'functionalSuiteHooks.xml'
80+
];
81+
82+
// create and return the iterator for these file paths
83+
$iterator = new Magento\FunctionalTestingFramework\Util\Iterator\File($paths);
84+
try {
85+
AspectMock\Test::double(
86+
Magento\FunctionalTestingFramework\Config\FileResolver\Root::class,
87+
['get' => $iterator]
88+
)->make();
89+
} catch (Exception $e) {
90+
echo "Suite directory not mocked.";
91+
}
92+
7293
function sortInterfaces($files)
7394
{
7495
$bottom = [];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Tests\unit\Magento\FunctionalTestFramework\Suite;
7+
8+
use AspectMock\Test as AspectMock;
9+
use Magento\FunctionalTestingFramework\ObjectManager\ObjectManager;
10+
use Magento\FunctionalTestingFramework\ObjectManagerFactory;
11+
use Magento\FunctionalTestingFramework\Suite\SuiteGenerator;
12+
use Magento\FunctionalTestingFramework\Suite\Generators\GroupClassGenerator;
13+
use Magento\FunctionalTestingFramework\Suite\Handlers\SuiteObjectHandler;
14+
use Magento\FunctionalTestingFramework\Suite\Parsers\SuiteDataParser;
15+
use Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler;
16+
use Magento\FunctionalTestingFramework\Test\Util\TestObjectExtractor;
17+
use Magento\FunctionalTestingFramework\Test\Parsers\TestDataParser;
18+
use Magento\FunctionalTestingFramework\Util\Manifest\DefaultTestManifest;
19+
use PHPUnit\Framework\TestCase;
20+
use tests\unit\Util\SuiteDataArrayBuilder;
21+
use tests\unit\Util\TestDataArrayBuilder;
22+
23+
class SuiteGeneratorTest extends TestCase
24+
{
25+
26+
/**
27+
* Tests generating a single suite given a set of parsed test data
28+
* @throws \Exception
29+
*/
30+
public function testGenerateSuite()
31+
{
32+
$suiteDataArrayBuilder = new SuiteDataArrayBuilder();
33+
$mockData = $suiteDataArrayBuilder
34+
->withName('basicTestSuite')
35+
->withAfterHook()
36+
->withBeforeHook()
37+
->includeTests(['simpleTest'])
38+
->includeGroups(['group1'])
39+
->build();
40+
41+
$testDataArrayBuilder = new TestDataArrayBuilder();
42+
$mockSimpleTest = $testDataArrayBuilder
43+
->withName('simpleTest')
44+
->withTestActions()
45+
->build();
46+
47+
$mockTestData = ['tests' => array_merge($mockSimpleTest)];
48+
$this->setMockTestAndSuiteParserOutput($mockTestData, $mockData);
49+
50+
// parse and generate suite object with mocked data
51+
$mockSuiteGenerator = SuiteGenerator::getInstance();
52+
$mockSuiteGenerator->generateSuite("basicTestSuite");
53+
54+
// assert that expected suite is generated
55+
$this->expectOutputString("Suite basicTestSuite generated to _generated/basicTestSuite." . PHP_EOL);
56+
}
57+
58+
/**
59+
* Tests generating all suites given a set of parsed test data
60+
* @throws \Exception
61+
*/
62+
public function testGenerateAllSuites()
63+
{
64+
$suiteDataArrayBuilder = new SuiteDataArrayBuilder();
65+
$mockData = $suiteDataArrayBuilder
66+
->withName('basicTestSuite')
67+
->withAfterHook()
68+
->withBeforeHook()
69+
->includeTests(['simpleTest'])
70+
->includeGroups(['group1'])
71+
->build();
72+
73+
$testDataArrayBuilder = new TestDataArrayBuilder();
74+
$mockSimpleTest = $testDataArrayBuilder
75+
->withName('simpleTest')
76+
->withTestActions()
77+
->build();
78+
79+
$mockTestData = ['tests' => array_merge($mockSimpleTest)];
80+
$this->setMockTestAndSuiteParserOutput($mockTestData, $mockData);
81+
82+
// parse and retrieve suite object with mocked data
83+
$exampleTestManifest = new DefaultTestManifest([], "sample/path");
84+
$mockSuiteGenerator = SuiteGenerator::getInstance();
85+
$mockSuiteGenerator->generateAllSuites($exampleTestManifest);
86+
87+
// assert that expected suites are generated
88+
$this->expectOutputString("Suite basicTestSuite generated to _generated/basicTestSuite." . PHP_EOL);
89+
}
90+
91+
/**
92+
* Tests attempting to generate a suite with no included/excluded tests and no hooks
93+
* @throws \Exception
94+
*/
95+
public function testGenerateEmptySuite()
96+
{
97+
$suiteDataArrayBuilder = new SuiteDataArrayBuilder();
98+
$mockData = $suiteDataArrayBuilder
99+
->withName('basicTestSuite')
100+
->build();
101+
unset($mockData['suites']['basicTestSuite'][TestObjectExtractor::TEST_BEFORE_HOOK]);
102+
unset($mockData['suites']['basicTestSuite'][TestObjectExtractor::TEST_AFTER_HOOK]);
103+
104+
$mockTestData = null;
105+
$this->setMockTestAndSuiteParserOutput($mockTestData, $mockData);
106+
107+
// set expected error message
108+
$this->expectExceptionMessage("Suites must not be empty. Suite: \"basicTestSuite\"");
109+
110+
// parse and generate suite object with mocked data
111+
$mockSuiteGenerator = SuiteGenerator::getInstance();
112+
$mockSuiteGenerator->generateSuite("basicTestSuite");
113+
}
114+
115+
/**
116+
* Function used to set mock for parser return and force init method to run between tests.
117+
*
118+
* @param array $testData
119+
* @throws \Exception
120+
*/
121+
private function setMockTestAndSuiteParserOutput($testData, $suiteData)
122+
{
123+
$property = new \ReflectionProperty(SuiteGenerator::class, 'SUITE_GENERATOR_INSTANCE');
124+
$property->setAccessible(true);
125+
$property->setValue(null);
126+
127+
// clear test object handler value to inject parsed content
128+
$property = new \ReflectionProperty(TestObjectHandler::class, 'testObjectHandler');
129+
$property->setAccessible(true);
130+
$property->setValue(null);
131+
132+
// clear suite object handler value to inject parsed content
133+
$property = new \ReflectionProperty(SuiteObjectHandler::class, 'SUITE_OBJECT_HANLDER_INSTANCE');
134+
$property->setAccessible(true);
135+
$property->setValue(null);
136+
137+
$mockDataParser = AspectMock::double(TestDataParser::class, ['readTestData' => $testData])->make();
138+
$mockSuiteDataParser = AspectMock::double(SuiteDataParser::class, ['readSuiteData' => $suiteData])->make();
139+
$mockGroupClass = AspectMock::double(
140+
GroupClassGenerator::class,
141+
['generateGroupClass' => 'namespace']
142+
)->make();
143+
$mockSuiteClass = AspectMock::double(SuiteGenerator::class, ['generateRelevantGroupTests' => null])->make();
144+
$instance = AspectMock::double(
145+
ObjectManager::class,
146+
['create' => function ($clazz) use (
147+
$mockDataParser,
148+
$mockSuiteDataParser,
149+
$mockGroupClass,
150+
$mockSuiteClass
151+
) {
152+
if ($clazz == TestDataParser::class) {
153+
return $mockDataParser;
154+
}
155+
if ($clazz == SuiteDataParser::class) {
156+
return $mockSuiteDataParser;
157+
}
158+
if ($clazz == GroupClassGenerator::class) {
159+
return $mockGroupClass;
160+
}
161+
if ($clazz == SuiteGenerator::class) {
162+
return $mockSuiteClass;
163+
}
164+
}]
165+
)->make();
166+
// bypass the private constructor
167+
AspectMock::double(ObjectManagerFactory::class, ['getObjectManager' => $instance]);
168+
169+
$property = new \ReflectionProperty(SuiteGenerator::class, 'groupClassGenerator');
170+
$property->setAccessible(true);
171+
$property->setValue($instance, $instance);
172+
173+
}
174+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
3+
namespace Group;
4+
5+
use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler;
6+
use Magento\FunctionalTestingFramework\DataGenerator\Persist\DataPersistenceHandler;
7+
8+
/**
9+
* Group class is Codeception Extension which is allowed to handle to all internal events.
10+
* This class itself can be used to listen events for test execution of one particular group.
11+
* It may be especially useful to create fixtures data, prepare server, etc.
12+
*
13+
* INSTALLATION:
14+
*
15+
* To use this group extension, include it to "extensions" option of global Codeception config.
16+
*/
17+
class functionalSuiteHooks extends \Codeception\GroupObject
18+
{
19+
public static $group = 'functionalSuiteHooks';
20+
private $testCount = 1;
21+
private $preconditionFailure = null;
22+
private $currentTestRun = 0;
23+
private static $HOOK_EXECUTION_INIT = "\n/******** Beginning execution of functionalSuiteHooks suite %s block ********/\n";
24+
private static $HOOK_EXECUTION_END = "\n/******** Execution of functionalSuiteHooks suite %s block complete ********/\n";
25+
private $create;
26+
27+
public function _before(\Codeception\Event\TestEvent $e)
28+
{
29+
// increment test count per execution
30+
$this->currentTestRun++;
31+
$this->executePreConditions();
32+
33+
if ($this->preconditionFailure != null) {
34+
//if our preconditions fail, we need to mark all the tests as incomplete.
35+
$e->getTest()->getMetadata()->setIncomplete($this->preconditionFailure);
36+
}
37+
}
38+
39+
40+
private function executePreConditions()
41+
{
42+
if ($this->currentTestRun == 1) {
43+
print sprintf(self::$HOOK_EXECUTION_INIT, "before");
44+
45+
try {
46+
$webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver');
47+
48+
// close any open sessions
49+
if ($webDriver->webDriver != null) {
50+
$webDriver->webDriver->close();
51+
$webDriver->webDriver = null;
52+
}
53+
54+
// initialize the webdriver session
55+
$webDriver->_initializeSession();
56+
$webDriver->amOnPage("some.url");
57+
$createFields['someKey'] = "dataHere";
58+
$createThis = DataObjectHandler::getInstance()->getObject("createThis");
59+
$this->create = new DataPersistenceHandler($createThis, [], $createFields);
60+
$this->create->createEntity();
61+
62+
// reset configuration and close session
63+
$this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver')->_resetConfig();
64+
$webDriver->webDriver->close();
65+
$webDriver->webDriver = null;
66+
} catch (\Exception $exception) {
67+
$this->preconditionFailure = $exception->getMessage();
68+
}
69+
70+
print sprintf(self::$HOOK_EXECUTION_END, "before");
71+
}
72+
}
73+
74+
public function _after(\Codeception\Event\TestEvent $e)
75+
{
76+
$this->executePostConditions();
77+
}
78+
79+
80+
private function executePostConditions()
81+
{
82+
if ($this->currentTestRun == $this->testCount) {
83+
print sprintf(self::$HOOK_EXECUTION_INIT, "after");
84+
85+
try {
86+
$webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver');
87+
88+
// close any open sessions
89+
if ($webDriver->webDriver != null) {
90+
$webDriver->webDriver->close();
91+
$webDriver->webDriver = null;
92+
}
93+
94+
// initialize the webdriver session
95+
$webDriver->_initializeSession();
96+
$webDriver->amOnPage("some.url");
97+
$webDriver->deleteEntityByUrl("deleteThis");
98+
99+
// reset configuration and close session
100+
$this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver')->_resetConfig();
101+
$webDriver->webDriver->close();
102+
$webDriver->webDriver = null;
103+
} catch (\Exception $exception) {
104+
print $exception->getMessage();
105+
}
106+
107+
print sprintf(self::$HOOK_EXECUTION_END, "after");
108+
}
109+
}
110+
}

0 commit comments

Comments
 (0)