Action groups
In the MFTF, you can re-use a group of actions, such as logging in as an administrator or a customer, declared in an XML file when you need to perform the same sequence of actions multiple times.
The following diagram shows the structure of a Functional Testing Framework action group:
Principles
The following conventions apply to Functional Testing Framework action groups:
- All action groups are declared in XML files and stored in the
<module>/Test/Mftf/ActionGroup/
directory. - Every filename ends with
ActionGroup
suffix. For exampeLoginAsAdminActionGroup.xml
. - Action group name should be the same as filename without extension.
- One
<actionGroup>
tag is allowed per action group XML file.
The XML format for the actionGroups
declaration is:
Copied to your clipboard<?xml version="1.0" encoding="UTF-8"?><actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"><actionGroup name=""><arguments><argument name=""/><argument name="" defaultValue=""/><argument name="" defaultValue="" type=""/></arguments></actionGroup></actionGroups>
Example
These examples build a declaration for a group of actions that grant authorization to the Admin area, and use the declaration in a test.
The Magento/Backend/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml <actionGroup>
relates to the functionality of the Magento_Backend module.
In test, the name and identifier of the <actionGroup>
is used as a reference in the ref
parameter, such as ref="LoginAsAdminActionGroup"
.
Create an action group declaration
To create the <actionGroup>
declaration:
Begin with a template for the
<actionGroup>
:Copied to your clipboard<?xml version="1.0" encoding="UTF-8"?><actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"><actionGroup name="{Action Group Name}"></actionGroup></actionGroups>Add actions to the
actionGroup
arguments:Copied to your clipboard<actionGroup name="LoginAsAdminActionGroup"><fillField stepKey="fillUsername" selector="#username" userInput="{{adminUser.username}}" /><fillField stepKey="fillPassword" selector="#password" userInput="{{adminUser.password}}" /><click stepKey="click" selector="#login" /></actionGroup>The
userInput
variable must contain a data value for test. Add a default data value for the variable to use in the most common cases. For this example, the default value is_defaultAdmin
.Copied to your clipboard<argument name="adminUser" defaultValue="_defaultAdmin"/>The following example shows the complete declaration:
Copied to your clipboard<?xml version="1.0" encoding="UTF-8"?><actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"><actionGroup name="LoginAsAdmin"><annotations><description>Login to Backend Admin using provided User Data. PLEASE NOTE: This Action Group does NOT validate that you are Logged In.</description></annotations><arguments><argument name="adminUser" type="entity" defaultValue="DefaultAdminUser"/></arguments><amOnPage url="{{AdminLoginPage.url}}" stepKey="navigateToAdmin"/><fillField selector="{{AdminLoginFormSection.username}}" userInput="{{adminUser.username}}" stepKey="fillUsername"/><fillField selector="{{AdminLoginFormSection.password}}" userInput="{{adminUser.password}}" stepKey="fillPassword"/><click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLogin"/><closeAdminNotification stepKey="closeAdminNotification"/></actionGroup></actionGroups>
Use the declaration in a test
In this test example, we want to add the following set of actions:
Copied to your clipboard<fillField selector="{{AdminLoginFormSection.username}}" userInput="{{adminUser.username}}" stepKey="fillUsername"/><fillField selector="{{AdminLoginFormSection.password}}" userInput="{{adminUser.password}}" stepKey="fillPassword"/><click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLogin"/>
Instead of adding this set of actions, use the LoginAsAdminActionGroup <actionGroup>
declaration in tests:
Reference the
LoginAsAdminActionGroup
action group:Copied to your clipboard<actionGroup stepKey="loginToAdminPanel" ref="LoginAsAdminActionGroup"/>Update the argument name/value pair to
adminUser
andCustomAdminUser
:Copied to your clipboard<actionGroup stepKey="loginToAdminPanel" ref="LoginAsAdminActionGroup"><argument name="adminUser" value="CustomAdminUser"/></actionGroup>
Data type usage
By default, an argument
expects an entire entity
when the type
value is not defined.
There are cases when you use a string instead of a whole entity.
For example, the following defines the replacement argument relevantString
using a primitive data type:
Copied to your clipboard<actionGroup name="fillExample"><arguments><argument name="relevantString" defaultValue="defaultString" type="string"/></arguments><fillField stepKey="fillField1" selector="#input" userInput="{{relevantString}}"/><click stepKey="clickSave" selector="#save"/><see stepKey="seeItWorked" selector="#outputArea" userInput="{{relevantString}}"/><click stepKey="clickParameterizedSelector" selector="{{SomeSection.parameterizedElement(relevantString)}}"/></actionGroup>
The string
argument type provides a method to pass a single piece of data to the <actionGroup>
during a test instead of passing an entire entity.
Explicitly define the argument value
Copied to your clipboard<actionGroup stepKey="fillWithStringLiteral" ref="fillExample"><argument name="relevantString" value="overrideString"/></actionGroup>
Use persisted data references to define the argument value
Copied to your clipboard<actionGroup stepKey="fillWithStringLiteral" ref="fillExample"><argument name="relevantString" value="$persistedData.field1$"/></actionGroup>
The relevantString
argument value points to the data created in the stepKey="persistedData"
test step.
field1
is a data key of the required data string.
Even with the persistedData
data entity, the Functional Testing Framework interprets the $persistedData.field1$
value as a string.
Define the argument value based on data entity resolution
The argument value points to a piece of data defined in a data.xml
file.
The field1
data contains the required string.
The Functional Testing Framework resolves {{myCustomEntity.field1}}
the same as it would in a selector
or userInput
attribute.
Copied to your clipboard<actionGroup stepKey="fillWithXmlData" ref="fillExample"><argument name="relevantString" value="{{myCustomEntity.field1}}"/></actionGroup>
Return a value
Action groups can return a value using a return
tag.
Copied to your clipboard<actionGroup name="GetOrderIdActionGroup"><seeElement selector="{{CheckoutSuccessMainSection.orderLink}}" stepKey="assertOrderLink"/><grabTextFrom selector="{{CheckoutSuccessMainSection.orderLink}}" stepKey="orderId"/><return value="{$orderId}" stepKey="returnOrderId"/></actionGroup>
The value returned can be accessed in later steps using action group step key {$getOrderId}
.
Copied to your clipboard<actionGroup ref="GetOrderIdActionGroup" stepKey="getOrderId"/><!--Filter the Order using Order ID --><actionGroup ref="FilterOrderGridByIdActionGroup" stepKey="filterOrderGridById"><argument name="orderId" value="{$getOrderId}"/></actionGroup>
Convention to return a value
The following conventions apply to action groups returning a value:
- Only action groups can return value. Use of
return
tag is dis-allowed in tests and suites. - An action group does not support multiple
return
tags. - For merging action groups,
return
is allowed only in one of the merging action groups. - Value returned by an action group can only be referenced within the scope that the action group is defined in (
test
,before/after
).
Optimizing action group structures
Structuring properly an action group increases code reusability and readability.
Starting with an action group such as:
Copied to your clipboard<actionGroup name="CreateCategory"><arguments><argument name="categoryEntity" defaultValue="_defaultCategory"/></arguments><seeInCurrentUrl url="{{AdminCategoryPage.url}}" stepKey="seeOnCategoryPage"/><click selector="{{AdminCategorySidebarActionSection.AddSubcategoryButton}}" stepKey="clickOnAddSubCategory"/><see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Category" stepKey="seeCategoryPageTitle"/><fillField selector="{{AdminCategoryBasicFieldSection.CategoryNameInput}}" userInput="{{categoryEntity.name}}" stepKey="enterCategoryName"/><click selector="{{AdminCategorySEOSection.SectionHeader}}" stepKey="openSEO"/><fillField selector="{{AdminCategorySEOSection.UrlKeyInput}}" userInput="{{categoryEntity.name_lwr}}" stepKey="enterURLKey"/><click selector="{{AdminCategoryMainActionsSection.SaveButton}}" stepKey="saveCategory"/><seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="assertSuccess"/><seeInTitle userInput="{{categoryEntity.name}}" stepKey="seeNewCategoryPageTitle"/><seeElement selector="{{AdminCategorySidebarTreeSection.categoryInTree(categoryEntity.name)}}" stepKey="seeCategoryInTree"/></actionGroup>
It can be reworked into more manageable pieces, as below. These smaller steps are easier to read, update, and reuse.
GoToCategoryGridAndAddNewCategory
Copied to your clipboard<actionGroup name="GoToCategoryGridAndAddNewCategory"><seeInCurrentUrl url="{{AdminCategoryPage.url}}" stepKey="seeOnCategoryPage"/><click selector="{{AdminCategorySidebarActionSection.AddSubcategoryButton}}" stepKey="clickOnAddSubCategory"/><see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Category" stepKey="seeCategoryPageTitle"/></actionGroup>FillInBasicCategoryFields
Copied to your clipboard<actionGroup name="FillInBasicCategoryFields"><arguments><argument name="categoryEntity" defaultValue="_defaultCategory"/></arguments><fillField selector="{{AdminCategoryBasicFieldSection.CategoryNameInput}}" userInput="{{categoryEntity.name}}" stepKey="enterCategoryName"/><click selector="{{AdminCategorySEOSection.SectionHeader}}" stepKey="openSEO"/><fillField selector="{{AdminCategorySEOSection.UrlKeyInput}}" userInput="{{categoryEntity.name_lwr}}" stepKey="enterURLKey"/></actionGroup>SaveAndVerifyCategoryCreation
Copied to your clipboard<actionGroup name="SaveAndVerifyCategoryCreation"><click selector="{{AdminCategoryMainActionsSection.SaveButton}}" stepKey="saveCategory"/><seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="assertSuccess"/><seeInTitle userInput="{{categoryEntity.name}}" stepKey="seeNewCategoryPageTitle"/><seeElement selector="{{AdminCategorySidebarTreeSection.categoryInTree(categoryEntity.name)}}" stepKey="seeCategoryInTree"/></actionGroup>
Elements reference
actionGroups
The <actionGroups>
element is a root element that contains XML configuration attributes.
Attribute | Value | Description |
---|---|---|
xmlns:xsi | "http://www.w3.org/2001/XMLSchema-instance" | Tells the XML parser to validate this document against a schema. |
xsi:noNamespaceSchemaLocation | "urn:magento:mftf:Test/etc/actionGroupSchema.xsd" | Relative path to the corresponding schema. |
It may contain one or more <actionGroup>
.
actionGroup
Attribute | Type | Use | Description |
---|---|---|---|
name | string | required | Identifier of the action group. |
extends | string | optional | Identifies the action group to extend. |
deprecated | string | optional | Used to warn about the future deprecation of the actionGroup. String will appear in Allure reports and console output at runtime. |
It may contain <arguments>
.
arguments
The <arguments>
element is a wrapper for an array of <argument>
elements.
argument
Attribute | Type | Use | Description |
---|---|---|---|
name | string | required | Identifier of an argument in the scope of the corresponding action group. |
defaultValue | string | optional | Provides a default data value. |
type | Possible values: string , entity (default). | optional | Defines the argument data type; Defaults to entity . |