MFTF: The Magento Functional Testing Framework in Detail
AI generated
PASS
expect()
Testing · MFTF · Magento 2 · Codeception
MFTF: The Magento Functional Testing Framework in Detail
XML-based tests for Magento core and modules

This article explains what the Magento Functional Testing Framework actually does, how its declarative XML structure fundamentally differs from imperative Cypress or Playwright code, and in which project phases MFTF still remains the right choice. Developers get a clear breakdown of when backend tests with MFTF make more sense than modern JavaScript E2E tests for the storefront.

14 min. read MFTF · XML · Codeception Magento 2.4.8 · Backend Testing Cypress · Playwright Comparison

1. What MFTF is and its role in the Magento ecosystem

The Magento Functional Testing Framework (MFTF) is Adobe's official framework for functional acceptance testing in Magento 2 and Adobe Commerce. It ships with every Magento core release, covers core functionality such as checkout, product management, customer accounts, and the admin area, and Adobe itself uses it to safeguard the platform code against regressions. Anyone building a module that interacts with core behavior finds thousands of existing tests in dev/tests/acceptance as a reference and a base to extend.

Unlike generic E2E frameworks, MFTF is explicitly tailored to the Magento domain: it already models concepts like admin grids, layered navigation, multi-website setups, and ACL roles as reusable building blocks. For agencies maintaining third-party modules or submitting their own extensions to the Marketplace, MFTF is therefore not an optional tool but part of the expected quality proof toward Adobe and the community.

2. MFTF versus Cypress and Playwright: declarative instead of imperative

The fundamental difference lies in the programming model: Cypress and Playwright are imperative, a test is JavaScript or TypeScript code that describes step by step what should happen, including conditions, loops, and arbitrary logic. MFTF is declarative, a test is defined as an XML document describing a sequence of named actions, without the test author needing to know a general-purpose programming language. That design choice noticeably lowers the entry barrier for QA teams without deep JavaScript knowledge.

MFTF also ships its own Magento-specific vocabulary of actions, such as fillField, waitForPageLoad, or seeInCurrentUrl, combined with predefined sections for standard pages like the admin login or the product form. Cypress and Playwright know none of this vocabulary, every selector and every wait condition has to be implemented on the project side. That makes modern JS tools more flexible, but noticeably more repetitive for Magento-typical flows like the admin login or saving a product, unless the team builds its own utility library first.

3. The MFTF architecture: Test, ActionGroup, Data, Page, and Section

MFTF structures tests into five XML file types with clearly separated responsibilities. A Section defines selectors for the UI elements of a page, a Page defines the URL and references its associated sections. An ActionGroup bundles a recurring sequence of interactions, such as a full admin login, into a parameterizable, reusable building block. A Test finally orchestrates action groups and individual actions into a complete test scenario with setup and teardown. Data XML files supply test data entities that get referenced inside tests instead of hardcoding values.

This modular separation pays off in large test suites: if a CSS selector in the admin product form changes, only the affected section needs updating, every test and action group referencing that section keeps working unchanged. The two examples below show an action group for the admin login and the matching section with the referenced selectors.


<?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="AdminLoginActionGroup">
        <annotations>
            <description>Logs in to the Magento Admin Panel with valid credentials.</description>
        </annotations>
        <arguments>
            <argument name="username" defaultValue="{{_ENV.MAGENTO_ADMIN_USERNAME}}"/>
            <argument name="password" defaultValue="{{_ENV.MAGENTO_ADMIN_PASSWORD}}"/>
        </arguments>
        <amOnPage url="{{AdminLoginPage.url}}" stepKey="navigateToAdminLogin"/>
        <waitForPageLoad stepKey="waitForLoginPage"/>
        <fillField selector="{{AdminLoginFormSection.username}}" userInput="{{username}}" stepKey="fillUsername"/>
        <fillField selector="{{AdminLoginFormSection.password}}" userInput="{{password}}" stepKey="fillPassword"/>
        <click selector="{{AdminLoginFormSection.signInButton}}" stepKey="clickSignIn"/>
        <waitForPageLoad stepKey="waitForDashboard"/>
    </actionGroup>
</actionGroups>

<?xml version="1.0" encoding="UTF-8"?>
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
    <section name="AdminLoginFormSection">
        <element name="username" type="input" selector="#username"/>
        <element name="password" type="input" selector="#login"/>
        <element name="signInButton" type="button" selector="button.action-login"/>
    </section>
    <section name="AdminProductGridSection">
        <element name="productNameCell" type="text" selector="td.col-name" parameterized="true"/>
        <element name="successMessage" type="text" selector="div.message-success"/>
    </section>
</sections>

4. Generated code: how MFTF turns XML into PHP and Codeception

MFTF is not a test runner itself, it's a code generation layer on top of Codeception, PHP's best-known acceptance testing framework. When you run vendor/bin/mftf generate:tests, MFTF reads all the XML files under Test/Mftf/Test, ActionGroup, Section, Page, and Data, resolves references and merges across modules, and produces concrete PHP classes in the dev/tests/acceptance/tests/_generated directory. Each of these classes is a regular Codeception Cest that uses the Selenium or Chromedriver WebDriver API.

This intermediate step has a decisive practical effect: the generated code isn't an implementation detail you can ignore, it's often the fastest way during debugging to understand why a test fails, since stack traces point to concrete lines in the generated PHP. Developers should never manually edit the generated code, since it gets overwritten on every re-run of generate:tests, but reading it as a debugging aid is perfectly reasonable.

5. When MFTF still makes sense today

MFTF remains the first choice wherever tests are tightly coupled to Magento core or module internals: admin workflows, ACL permissions, complex product type configurations, multi-source inventory, or the interplay between several third-party modules in the backend. Anyone submitting a module to the Adobe Commerce Marketplace can barely avoid MFTF tests, since the Marketplace quality guidelines explicitly list functional test coverage as an approval criterion and reviewers use existing MFTF suites as a reference point.

MFTF is also valuable as a regression net against future Magento core updates: since Adobe itself runs thousands of MFTF tests against every new core release, module developers benefit from the same test infrastructure and can integrate their own suites into the same CI run. For agencies maintaining several existing clients on classic, non-Hyvä themes, MFTF is often the only practical option too, because UI components and Knockout.js widgets are already covered by matching sections that a freshly set up JS test suite would otherwise have to rebuild from scratch.

6. When a modern JS E2E tool is the better fit

For the storefront of a Hyvä store, the recommendation flips. Hyvä relies consistently on Tailwind CSS and Alpine.js, a frontend stack for which MFTF has neither predefined sections nor any awareness of Alpine's internal state handling. Every interaction with an x-data component state would have to be reconstructed in MFTF via generic CSS selectors, whereas Cypress or Playwright operate directly in the same browser context real users interact with, and benefit from an active, well-maintained tooling community.

The feedback loop clearly favors JS tools too: a Cypress test runs in seconds in an interactive watch mode with time-travel debugging and live DOM snapshots, while an MFTF test first has to be generated and then run through a full Selenium session, which noticeably adds time per test run. Playwright adds native cross-browser support, network mocking, and visual regression testing with pixel comparison on top, all capabilities that aren't available in the MFTF ecosystem, or only through workarounds.

7. A concrete MFTF test example, walked through

The following example shows a complete MFTF test that creates a simple product as an admin user and verifies the success message. The annotations block documents feature, story, title, description, and severity, metadata MFTF also uses for test selection by group. The before block references the previously shown AdminLoginActionGroup, so the login flow doesn't need to be rewritten in every single test.

The actual test body fills form fields via referenced section selectors, clicks the save button, and uses see to verify that the expected success message appears in the DOM, functionally comparable to assertSee in classic Codeception tests. The after block ensures a clean logout at the end of the test, regardless of whether the test passed or failed.


<?xml version="1.0" encoding="UTF-8"?>
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
    <test name="AdminCreateSimpleProductTest">
        <annotations>
            <features value="Catalog"/>
            <stories value="Create Product"/>
            <title value="Admin can create a simple product"/>
            <description value="Verifies that an admin user can create a simple product and see the success message."/>
            <severity value="CRITICAL"/>
            <group value="catalog"/>
        </annotations>
        <before>
            <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
        </before>
        <amOnPage url="{{AdminProductNewPage.url}}" stepKey="navigateToNewProduct"/>
        <waitForPageLoad stepKey="waitForProductForm"/>
        <fillField selector="{{AdminProductFormSection.productName}}" userInput="Test Product 123" stepKey="fillProductName"/>
        <fillField selector="{{AdminProductFormSection.productSku}}" userInput="test-product-123" stepKey="fillProductSku"/>
        <fillField selector="{{AdminProductFormSection.productPrice}}" userInput="19.99" stepKey="fillProductPrice"/>
        <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickSave"/>
        <waitForPageLoad stepKey="waitForSave"/>
        <see selector="{{AdminProductGridSection.successMessage}}" userInput="You saved the product." stepKey="assertSuccessMessage"/>
        <after>
            <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutAsAdmin"/>
        </after>
    </test>
</tests>

8. Generating and running MFTF tests

The MFTF workflow always runs in two stages: generation, then execution. vendor/bin/mftf generate:tests translates all the XML sources into PHP and places them in the generated directory, optionally scoped to a specific test group or a single module. Only after that can Codeception actually run the generated tests against a running Magento instance and a configured Selenium or Chromedriver endpoint.

For day-to-day development work, a tight, targeted cycle pays off: generate and run a single test or a single group instead of rebuilding the entire suite on every change, which can take several minutes for larger modules. The environment configuration in .env and MFTF-specific configuration files centrally controls the base URL, admin credentials, and the browser endpoint for the whole project.


# Generate the PHP/Codeception test suite from MFTF XML sources
vendor/bin/mftf generate:tests

# Run a single generated test against the configured Selenium/WebDriver
vendor/bin/mftf run:test AdminCreateSimpleProductTest

# Run an entire test group, e.g. all catalog-related tests
vendor/bin/mftf run:group catalog

# Regenerate and run in one step, cleaning stale generated code first
vendor/bin/mftf generate:tests --force
vendor/bin/mftf run:test AdminCreateSimpleProductTest --remove

9. MFTF versus Cypress/Playwright, compared side by side

Both approaches are valid in their respective context, the table below lines up the most important decision dimensions. One thing to keep in mind: no row means a tool is categorically worse, only that it's structurally at a disadvantage in that particular scenario.

Aspect MFTF Cypress/Playwright Recommendation
Language/approach Declarative XML, unfamiliar to frontend teams JS/TS, familiar syntax Favor JS tools for frontend devs
Feedback loop Generation plus a full Selenium session Seconds, interactive watch mode Use Cypress/Playwright for fast iteration
Magento vocabulary Huge library of actions/sections Has to be built from scratch per project Use MFTF for core-adjacent tests
Marketplace compliance Expected quality proof Not part of the official process Use MFTF for module submissions
Hyvä storefront testing No awareness of Alpine.js state Native browser interaction, visual regression Use Cypress/Playwright for storefront E2E

As a contrasting example, the code below applies the same underlying idea, proving success after an action, this time as a Playwright test for a cart flow on a Hyvä storefront, noticeably more compact than the equivalent MFTF XML, but without its built-in Magento vocabulary.


import { test, expect } from '@playwright/test';

// Equivalent storefront flow written imperatively for a Hyvä theme frontend
test('customer can add a simple product to the cart', async ({ page }) => {
  await page.goto('/test-product-123.html');

  await page.getByRole('button', { name: 'Add to Cart' }).click();

  // Hyvä updates the mini cart via Alpine.js state, no full page reload
  await expect(page.locator('[data-cart-count]')).toHaveText('1');
  await expect(page.getByText('You added Test Product 123 to your shopping cart.')).toBeVisible();
});

In practice, most Magento projects do best with a deliberate split: MFTF for backend regression, module integrations, and wherever Marketplace compliance requires it, Cypress or Playwright for everything customers actually see and interact with in the Hyvä frontend. This split avoids duplicate test coverage and puts each tool exactly where it holds a structural advantage.

Mironsoft

MFTF, Cypress, and Playwright test strategy for Magento and Hyvä projects

Need a solid test strategy for your Magento project?

We build MFTF suites for backend and module regression, set up Cypress or Playwright for your Hyvä storefront, and wire both into a CI/CD pipeline that combines fast feedback with solid coverage.

MFTF test suites

Building admin, module, and Marketplace compliance tests

Hyvä storefront E2E

Setting up Cypress/Playwright for checkout and purchase flows

CI/CD integration

Wiring both test layers into your pipeline automatically

10. Summary

MFTF solves a different problem than Cypress or Playwright: it describes tests declaratively in XML, generates PHP code for Codeception from it, and ships an extensive, Magento-specific vocabulary of actions and sections for backend and module testing. The Test, ActionGroup, Data, Page, and Section architecture allows clean reuse across large test suites, though at the cost of a slower feedback loop compared to modern JavaScript tools.

For a Hyvä store's storefront, a modern E2E tool remains the better choice, since it operates directly in the same browser context real customers use, delivers faster feedback, and natively understands Alpine.js interactions. The most pragmatic solution for most Magento projects isn't an either-or decision, but a deliberate combination: MFTF for core and module regression, a JS tool for everything customers actually experience in the frontend.

MFTF and Modern E2E Tools, the Essentials at a Glance

XML instead of JavaScript

MFTF describes tests declaratively and generates runnable PHP/Codeception code from them.

Modular architecture

Test, ActionGroup, Data, Page, and Section fit together as reusable building blocks.

Where MFTF fits

Core/module regression, admin workflows, and Marketplace quality gates.

Where Cypress/Playwright fits

Hyvä storefront, fast iteration, visual regression, and cross-browser testing.

11. FAQ: MFTF, Cypress, and Playwright

1What is the Magento Functional Testing Framework (MFTF)?
Adobe's official framework for functional acceptance testing in Magento 2. Tests are defined declaratively in XML, MFTF generates PHP code for Codeception from them.
2How does MFTF fundamentally differ from Cypress or Playwright?
MFTF is declarative and XML-based, Cypress/Playwright are imperative in JS/TS. MFTF also ships a Magento-specific vocabulary of actions and sections.
3What are Test, ActionGroup, Data, Page, and Section in MFTF?
The five MFTF file types: Section for selectors, Page for URLs, ActionGroup for reusable interaction sequences, Data for test data, Test orchestrates everything together.
4What code does MFTF generate under the hood?
PHP classes in the dev/tests/acceptance/tests/_generated directory. Each class is a Codeception Cest that uses Selenium or Chromedriver.
5Does MFTF use Selenium WebDriver to run tests?
Yes, the generated Codeception tests automate the browser via Selenium or Chromedriver, configured through MFTF's environment variables.
6When should I use MFTF instead of a modern JS E2E tool?
For admin workflows, module integration tests, backend configurations, and Marketplace submissions, where MFTF tests are expected as quality proof.
7Is MFTF suitable for testing Hyvä storefronts?
Only to a limited extent. MFTF has neither Hyvä sections nor Alpine.js state awareness. For storefront testing, Cypress or Playwright are a much better fit.
8Is MFTF mandatory for Marketplace modules?
The Marketplace quality guidelines list functional test coverage as a criterion, and MFTF tests are the standard proof reviewers expect.
9How do I generate and run MFTF tests?
vendor/bin/mftf generate:tests translates XML into PHP, then vendor/bin/mftf run:test or run:group executes the generated test or group against the configured instance.
10Can MFTF and Cypress/Playwright be combined in the same project?
Yes, that is the recommended strategy: MFTF for backend/module regression, Cypress or Playwright for Hyvä storefront tests, both in the same CI/CD pipeline.