Fixture
An FTF fixture is a list of properties of the Magento entity under test.
A fixture is represented as an XML file located in the Fixture
directory that corresponds to a module in <magento2_root_dir>/dev/tests/functional/tests/app/Magento/functional
. Example for Widget
:
<magento2_root_dir>/dev/tests/functional/tests/app/Magento/Widget/Test/Fixture/Widget.xml
You will need fixture:
- as test data for particular set
- as precondition for the test
In this chapter, we will create a new fixture and modify it, considering different use cases.
To apply any changes in fixture, run generate tool:
1
cd <magento2_root_dir>/dev/tests/functional/utils
1
php generate.php
This tool creates PHP classes that are used by the test.
You can check fixture PHP class in corresponding module in the <magento2_root_dir>/dev/tests/functional/generated/Magento
directory.
Create new fixture
Let’s imagine that we want to create new fixture to test our Widget module.
Magento has a tool, generateFixtureXml.php,
, to automatically generate fixture with parameters indicated in arguments. It is located in <magento2_root_dir>/dev/tests/functional/utils
.
1
cd <magento2_root_dir>/dev/tests/functional/utils
1
php -f generateFixtureXml.php -- --name widget --entity_type widget_instance --collection Magento\\Widget\\Model\\Resource\\Widget\\Instance\\Collection
Please note that the generateFixtureXml tool does not replace an existing XML fixture. For example, if you already have Widget.xml
fixture, you cannot create new one with the same name.
To work with generateFixtureXml tool, Magento must be installed.
In the following table see generateFixtureXml
arguments.
Argument | Semantics | Value from command above | Note | |
---|---|---|---|---|
--name |
Name of fixture. | widget |
Required | |
--type |
Table type for the entity. Can be eav , flat , composite . |
flat |
Default value: flat . |
|
--entity_type |
Database table name, where entity data is stored. | widget_instance |
Required | |
--collection |
Collection to generate data sets | Magento\\Widget\\Model\\Resource\\Widget\\Instance\\Collection |
Required. Escape all backslashes. | |
--help |
List of arguments with definitions. |
This tool creates a new fixture using data from a database table you specified using the --entity_type
argument.
Following is the generated Widget fixture located in <magento2_root_dir>/dev/tests/functional/tests/app/Magento/Widget/Test/Fixture/Widget.xml
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
<fixture name="widget"
module="Magento_Widget"
type="flat"
collection="Magento\Widget\Model\Resource\Widget\Instance\Collection"
repository_class="Magento\Widget\Test\Repository\Widget"
handler_interface="Magento\Widget\Test\Handler\Widget\WidgetInterface"
class="Magento\Widget\Test\Fixture\Widget"
entity_type="widget_instance">
<field name="instance_id" is_required="1"/>
<field name="instance_type" is_required="0"/>
<field name="theme_id" is_required="0"/>
<field name="title" is_required="0"/>
<field name="store_ids" is_required="0"/>
<field name="sort_order" is_required="0"/>
<field name="widget_parameters" is_required="0"/>
</fixture>
</config>
To generate PHP classes, enter the following commands in the order shown:
1
cd <magento2_root_dir>/dev/tests/functional/utils
1
php generate.php
That’s it!
For a detailed description of XML structure, see next section.
Read and update your new fixture
Let’s look closer at fixture structure.
<config>
is a root node that defines path tofixture.xsd
schema.<fixture>
defines fixture configuration.<data_config>
defines additional fixture configuration for the fixture.<field>
defines field in fixture.
Following table describes <fixture>
attributes.
<fixture> attribute |
Semantics | Value | Example | Is required? |
---|---|---|---|---|
name |
Name of fixture. | string | catalogProductSimple | required |
module |
Name of the module in which to place the fixture. | string | Magento_Catalog | required |
class |
Path to the PHP class. Generator will use this path to locate automatically generated PHP file. | string | Magento\Catalog\Test\Fixture\CatalogProductSimple | required |
type |
Table type for the entity. | eav , flat , virtual , composite |
eav | optional |
entity_type |
Database table name where the entity data is stored. Specify more than one database table as a comma-separated list (for example, "eav_attribute, catalog_eav_attribute" ) and assign type = "composite" . |
string | catalog_product | optional |
product_type |
Type of product. Applicable only for product fixtures. | string | simple | optional |
collection |
Collection to generate data sets. It is taken from <magento2_root_dir>/app/code/Magento . |
string | Magento\Catalog\Model\Resource\Product\Collection | optional |
identifier |
Field used to create data set names in the repository. | string | sku | optional |
repository_class |
Reference to the repository class. | string | Magento\Catalog\Test\Repository\CatalogProductSimple | optional |
handler_interface |
Reference to the handler interface class. | string | Magento\Catalog\Test\Handler\CatalogProductSimple\CatalogProductSimpleInterface | optional |
extends |
Reference to the class from which you want to extend. | string | \Magento\Widget\Test\Fixture\Widget | optional |
The following table describes <field>
attributes.
<field> attribute |
Semantics | Value | Example | Is required? |
---|---|---|---|---|
name |
Field name. | string | layout_updates | required |
is_required |
Specifies whether field is required on the form. | 1 - required, 0 - optional | 1 | optional |
group |
Tab name that contains field (for example, title field is placed on Storefront properties tab on widget creation page). |
string | storefront_properties | optional |
source |
Class that prepares field data for use. See Add the data source to the fixture field. | string | Magento\Widget\Test\Fixture\Widget\LayoutUpdates | optional |
repository |
Reference to the class that stores data sets for the field. More details about the repository. | string | Magento\Widget\Test\Repository\Widget\LayoutUpdates | optional |
The following image shows how XML is connected with GUI of your new widget.
Orange arrows show relations between <field>
nodes of fixture and GUI element of Magento widget, that we are going to test.
As you can see, we added some information to the picture. New text is highlighted in orange.
For convenience, we added a group
attribute that matches the name of the tab where the UI elements are located. Except for instance_id
, this field does not display which is why it belongs to the null group.
We also defined a new field, layout_updates
on the UI but this field is absent from the list of fields in our XML fixture. This is because the field is not present in the database table widget_instance
specified by the entity_type
.
Let’s manually add a new field and group
attribute to the Widget.xml
. See what we have now.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
<fixture name="widget"
module="Magento_Widget"
type="flat"
collection="Magento\Widget\Model\Resource\Widget\Instance\Collection"
repository_class="Magento\Widget\Test\Repository\Widget"
handler_interface="Magento\Widget\Test\Handler\Widget\WidgetInterface"
class="Magento\Widget\Test\Fixture\Widget"
entity_type="widget_instance">
<field name="instance_id" is_required="1" group="null" />
<field name="instance_type" is_required="0" group="settings" />
<field name="theme_id" is_required="0" group="settings" />
<field name="title" is_required="0" group="storefront_properties" />
<field name="store_ids" is_required="0" group="storefront_properties" />
<field name="sort_order" is_required="0" group="storefront_properties" />
<field name="widget_parameters" is_required="0" group="frontend_options" />
<field name="layout_updates" is_required="0" group="storefront_properties" />
</fixture>
</config>
To apply the changes, enter the following commands:
1
cd <magento2_root_dir>/dev/tests/functional/utils
1
php generate.php
Add a repository to the fixture field
Now we have a new fixture for Widget. All fields are defined and ready to take test data. Let’s assume that we are not focused on layout updates functionality and want to use pre-defined data.
For this goal, link to the repository where all test data has already been defined.
1
<field name="layout_updates" repository="Magento\Widget\Test\Repository\Widget\LayoutUpdates" group="storefront_properties" />
Repository is located in Repository
directory of corresponding module. Repository
directory contains a subdirectory with the name of fixture, and repository XML file in it with the name of fixture field.
The repository is located in <magento2_root_dir>/dev/tests/functional/app/Magento/Widget/Test/Repository/Widget/LayoutUpdates.xml
.
Following is the code of LayoutUpdates.xml
. It specifies two data sets that you can choose to define in your test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/Magento/Mtf/Repository/etc/repository.xsd">
<repository class="Magento\Widget\Test\Repository\Widget\LayoutUpdates">
<dataset name="all_pages">
<field name="0" xsi:type="array">
<item name="page_group" xsi:type="string">Generic Pages/All Pages</item>
<item name="block" xsi:type="string">Main Content Area</item>
</field>
</dataset>
<dataset name="on_category">
<field name="0" xsi:type="array">
<item name="page_group" xsi:type="string">Categories/Non-Anchor Categories</item>
<item name="for" xsi:type="string">Yes</item>
<item name="entities" xsi:type="string">category::default_subcategory</item>
<item name="block" xsi:type="string">Main Content Area</item>
</field>
</dataset>
</repository>
</config>
To apply changes, enter following commands:
1
cd <magento2_root_dir>/dev/tests/functional/utils
1
php generate.php
Add data source to fixture field
Our new field layout_updates
is complex and contains different elements and logic, depending on the type of layout chosen.
You can use a data source that provides additional processing of the field (for example, parsing or creation of new field).
All data source logic is defined in a PHP file which must be linked as specified in the field’s source
attribute.
It is located in Fixture
directory of corresponding module. That contains subdirectory with the name of fixture, and source class in it with the name of fixture field. See the following example.
1
2
3
4
5
<field name="layout_updates"
is_required="0"
repository="Magento\Widget\Test\Repository\Widget\LayoutUpdates"
source="Magento\Widget\Test\Fixture\Widget\LayoutUpdates"
group="storefront_properties" />
Let’s see our data source file <magento2_root_dir>/dev/tests/functional/tests/app/Magento/Widget/Test/Fixture/Widget/LayoutUpdates.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
namespace Magento\Widget\Test\Fixture\Widget;
use Magento\Mtf\Fixture\FixtureFactory;
use Magento\Mtf\Fixture\DataSource;
use Magento\Mtf\Repository\RepositoryFactory;
/**
* Prepare Layout Updates for widget.
*/
class LayoutUpdates extends DataSource
{
/**
* @constructor
* @param RepositoryFactory $repositoryFactory
* @param FixtureFactory $fixtureFactory
* @param array $params
* @param array $data
*/
public function __construct(
RepositoryFactory $repositoryFactory,
FixtureFactory $fixtureFactory,
array $params,
array $data = []
) {
$this->params = $params;
if (isset($data['dataset']) && isset($this->params['repository'])) {
$this->data = $repositoryFactory->get($this->params['repository'])->get($data['dataset']);
foreach ($this->data as $index => $layouts) {
if (isset($layouts['entities'])) {
$explodeValue = explode('::', $layouts['entities']);
$fixture = $fixtureFactory->createByCode($explodeValue[0], ['dataset' => $explodeValue[1]]);
$fixture->persist();
$this->data[$index]['entities'] = $fixture;
}
}
} else {
$this->data = $data;
}
}
}
It is important to note that you should mention repository in data source class to use it for fixture field:
1
$this->data = $repositoryFactory->get($this->params['repository'])->get($data['dataset']);
To apply the changes, enter the following commands:
1
cd <magento2_root_dir>/dev/tests/functional/utils
1
php generate.php
Merge fixtures
We have a module that adds new field to Widget module.
We can create file that adds field new_field
to our widget fixture.
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
<fixture name="widget">
<field name="new_field" is_required="0" group="storefront_properties" />
</fixture>
</config>
To apply the changes, enter the following commands:
1
cd <magento2_root_dir>/dev/tests/functional/utils
1
php generate.php
new_field
has been added in fixture Widget.php
.
Extend fixture
Let’s assume that you want to add new fixture based on our Widget.xml
fixture to another Magento entity.
To do that you should supplement your Widget.xml
code with extends
attribute in <fixture>
node. As you already know, extends
value stores a link to the class from which you want to extend your fixture.
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
<fixture name="adWidget"
repository_class="Magento\AdWidget\Test\Repository\AdWidget"
handler_interface="Magento\AdWidget\Test\Handler\AdWidget\AdWidgetInterface"
class="Magento\AdWidget\Test\Fixture\AdWidget"
extends="\Magento\Widget\Test\Fixture\Widget">
<field name="custom_field" repository="Magento\AdWidget\Test\Repository\AdWidget\CustomField" group="storefront_properties" />
</fixture>
</config>
In this example you will create a new fixture PHP class AdWidget that extends Widget fixture. It creates a fixture with the same name, and a field named custom_field
.
To generate your new fixture PHP class, enter the following commands:
1
cd <magento2_root_dir>/dev/tests/functional/utils
1
php generate.php