Magento 2 and Automated Testing: Reducing Bugs in Custom Modules

Why Automated Testing Matters in Magento 2

Let’s be honest—custom Magento 2 modules peut être buggy. Even small changes can break things unexpectedly. That’s where automated test comes in. Instead of manually clicking through your store every time you make an update, automated tests do the heavy lifting for you. They catch problèmes before they reach production, saving you time, money, and headaches.

Magento 2 supports three main types of automated tests:

  • Unit Tests – Test individual PHP classes in isolation.
  • Integration Tests – Check how different composants work together.
  • Functional Tests – Simulate real utilisateur interactions (like clicking buttons).

Setting Up PHPUnit for Unit Testing

Premièrement, make sure PHPUnit is installed. If you’re using Composer (which you devrait être), run:

composer require --dev phpunit/phpunit

Maintenant, let’s say you have a simple classe helper in your custom module at app/code/Vendor/Module/Helper/Data.php:

<?php
namespace Vendor\Module\Helper;

class Data
{
    public function addNumbers($a, $b)
    {
        return $a + $b;
    }
}

To test this, create a test fichier at app/code/Vendor/Module/Test/Unit/Helper/DataTest.php:

<?php
namespace Vendor\Module\Test\Unit\Helper;

use PHPUnit\Framework\TestCase;
use Vendor\Module\Helper\Data;

class DataTest extends TestCase
{
    public function testAddNumbers()
    {
        $helper = new Data();
        $this->assertEquals(5, $helper->addNumbers(2, 3));
    }
}

Run the test with:

vendor/bin/phpunit app/code/Vendor/Module/Test/Unit/Helper/DataTest.php

If everything’s correct, you’ll see a green "OK" message. If not, PHPUnit tells you exactly what went wrong.

Integration Testing in Magento 2

Integration tests are where Magento’s real power shines. They test how your code interacts with the framework. Let’s test a basic model.

Assume you have a model at app/code/Vendor/Module/Model/Example.php:

<?php
namespace Vendor\Module\Model;

use Magento\Framework\Model\AbstractModel;

class Example extends AbstractModel
{
    protected function _construct()
    {
        $this->_init('Vendor\Module\Model\ResourceModel\Example');
    }
}

Create an test d'intégration at app/code/Vendor/Module/Test/Integration/Model/ExampleTest.php:

<?php
namespace Vendor\Module\Test\Integration\Model;

use Magento\TestFramework\ObjectManager;
use PHPUnit\Framework\TestCase;
use Vendor\Module\Model\Example;

class ExampleTest extends TestCase
{
    public function testModelLoad()
    {
        $objectManager = ObjectManager::getInstance();
        $model = $objectManager->create(Example::class);
        $model->setData(['name' => 'Test']);
        $model->save();
        
        $loadedModel = $objectManager->create(Example::class);
        $loadedModel->load($model->getId());
        
        $this->assertEquals('Test', $loadedModel->getName());
    }
}

Run it with:

vendor/bin/phpunit app/code/Vendor/Module/Test/Integration/Model/ExampleTest.php

Functional Testing with MFTF

Magento Functional Testing Framework (MFTF) simulates real utilisateur actions. Premièrement, install it:

composer require --dev magento/magento2-functional-testing-framework

Let’s test adding a product to the cart. Create a test at dev/tests/acceptance/tests/functional/Vendor/Module/AddToCartTest.xml:

<?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="AddSimpleProductToCartTest">
        <annotations>
            <title value="Add simple product to cart"/>
            <description value="Test adding a simple product to the shopping cart"/>
        </annotations>
        
        <before>
            <createData entity="_defaultCategory" stepKey="createCategory"/>
            <createData entity="_defaultProduct" stepKey="createProduct">
                <requiredEntity createDataKey="createCategory"/>
            </createData>
        </before>
        
        <amOnPage url="{{StorefrontProductPage.url($$createProduct.custom_attributes[url_key]$$)}}" stepKey="goToProductPage"/>
        <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart"/>
        <waitForElementVisible selector="{{StorefrontMessagesSection.success}}" stepKey="waitForSuccessMessage"/>
        <see userInput="You added $$createProduct.name$$ to your shopping cart." selector="{{StorefrontMessagesSection.success}}" stepKey="seeSuccessMessage"/>
    </test>
</tests>

Run the test with:

vendor/bin/mftf run:test AddSimpleProductToCartTest

Continuous Integration (CI) for Automated Testing

Running tests manually is good, but integnote them into your CI pipeline is better. Here’s a basic .github/workflows/tests.yml for GitHub Actions:

name: Magento 2 Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Set up PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '7.4'
          extensions: dom, curl, libxml, mbstring, openssl, pdo_mysql, tokenizer, xml, zip
          coverage: none
          
      - name: Install dependencies
        run: |
          composer install --no-interaction --no-progress
          
      - name: Run unit tests
        run: vendor/bin/phpunit app/code/Vendor/Module/Test/Unit/
        
      - name: Run integration tests
        run: vendor/bin/phpunit app/code/Vendor/Module/Test/Integration/

Common Testing Pitfalls to Avoid

  • Not mocking dependencies – Unit tests should test one class at a time.
  • Over-reliance on test d'intégrations – They’re slower than test unitaires.
  • Ignoring test coverage – Aim for at least 70% coverage.
  • Forgetting edge cases – Test invalid inputs, empty states, etc.

Réflexions finales

Automated test might seem like extra work upfront, but it pays off quickly. Bugs caught early are cheaper to correctif, and you’ll déployer with confidence. Start small—add a few test unitaires, then expand to integration and fonctional tests.

Need help with your Magento 2 modules? Check out our extensions or optimized hosting solutions to keep your store running smoothly!