Functional tests on your Magento store with Behat Mink

Do not be afraid of regressions anymore with this module that will let you test your Magento store at any time. Test adding to cart, authentication, navigation or any other page-sensitive operation of your shop.

What is Mink?

Mink is simply a library that can virtualize a web browser in PHP. It works with drivers (Goutte, Zombie, Selenium, …) and can automate testing of the interface of your site. Each driver has its advantages and disadvantages which are very well explained on the official website: http://mink.behat.org/#different-browsers-drivers.

You do not need to install Behat Mink since it is included (thanks to PHAR package) in the Magento extension described in this article.

Overview

The test suite can be run from the command line or from a browser (if the driver used is compatible).

Here is the result of a single test suite launched in command line and from a browser:

Installation

Extension is available on GitHub: https://github.com/jreinke/magento-mink

You have 2 ways to install it:

  1. Manual installation : download package here, unzip in Magento root folder, then clean cache.
  2. Installation with modgit:

    modgit -e README.md clone mink https://github.com/jreinke/magento-mink.git

    See a full example of how to use modgit here.

Writing tests

app/code/local/Company/Module/Test/Mink/Catalog.php

<?php
/**
 * For the test to be considered, you must:
 * - put the module in app/code/local
 * - put the class in Company/Module/Test/Mink/ folder
 * - extend the class JR_Mink_Test_Mink
 * - start the method with the keyword test*
 */
class Company_Module_Test_Mink_Catalog extends JR_Mink_Test_Mink
{
    public function testAddProductToCart()
    {
        $this->section('TEST ADD PRODUCT TO CART');
        $this->setCurrentStore('default');
        $this->setDriver('goutte');
        $this->context();
 
        // Go to home
        $this->output($this->bold('Go to home'));
        $url = Mage::getStoreConfig('web/unsecure/base_url');
        $this->visit($url);
        $category = $this->find('css', '#nav .nav-1-1 a');
        if (!$category) {
            return false;
        }
 
        // Go to product list
        $this->output($this->bold('Go to product list'));
        $this->visit($category->getAttribute('href'));
        $product = $this->find('css', '.category-products li.first a');
        if (!$product) {
            return false;
        }
 
        // Go to product view
        $this->output($this->bold('Go to product view'));
        $this->visit($product->getAttribute('href'));
        $form = $this->find('css', '#product_addtocart_form');
        if ($form) {
            $addToCartUrl = $form->getAttribute('action');
            $this->visit($addToCartUrl);
            $this->attempt(
                $this->find('css', '#shopping-cart-table'),
                'Product added to cart successfully',
                'Error adding product to cart'
            );
        }
    }
}

app/code/local/Company/Module/Test/Mink/Customer.php

<?php
/**
 * For the test to be considered, you must:
 * - put the module in app/code/local
 * - put the class in Company/Module/Test/Mink/ folder
 * - extend the class JR_Mink_Test_Mink
 * - start the method with the keyword test*
 */
class Company_Module_Test_Mink_Customer extends JR_Mink_Test_Mink
{
    public function testLogin()
    {
        $this->section('TEST CUSTOMER LOGIN');
        $this->setDriver('goutte');
 
        $this->output($this->bold('Go to home'));
        $url = Mage::getStoreConfig('web/unsecure/base_url');
        $this->visit($url);
 
        $loginUrl = $this->find('css', 'ul.links li.last a');
        if ($loginUrl) {
            $this->visit($loginUrl->getAttribute('href'));
        }
 
        $login = $this->find('css', '#email');
        $pwd = $this->find('css', '#pass');
        $submit = $this->find('css', '#send2');
        if ($login && $pwd && $submit) {
            $email = '[email protected]';
            $password = 'johndoe';
            $this->output(sprintf("Try to authenticate '%s' with password '%s'", $email, $password));
            $login->setValue($email);
            $pwd->setValue($password);
            $submit->click();
            $this->attempt(
                $this->find('css', 'div.welcome-msg'),
                'Customer successfully logged in',
                'Error authenticating customer'
            );
        }
    }
}

Running tests

If you want to run form the command line:

php shell/mink.php

If you want to run from the browser:

http://dev.magento.local/shell/mink.php

Note that all available Mink drivers are not necessarily compatible with a test launch from the browser. In our example, the Goutte driver is compatible but this is not the case for the Zombie driver for example.

Output renderer

The extension allows you to get the display you want when running your tests. Here are some examples:

<?php
$this->section('SECTION #1'); // ---------- SECTION #1 ----------
$this->context(false); // displays the current store view without the cache configuration
$this->br(2); // Displays 2 empty lines
$this->output('Go to product page'); // Displays 'Go to product page'
$this->output($this->bold('Go to product page')); // Displays 'Go to product page' in bold
$this->success('Customer successfully logged in'); // Displays the message in green
$this->error('An error occured'); // Displays the message in red

7 Responses to “Functional tests on your Magento store with Behat Mink”

  1. Very slick. Thanks for the nice tutorial.

  2. shashikant says:

    Great post definitely useful for ecommerce companies

  3. gondo says:

    hi
    why did you choose this file structure?
    is there any special reason behind this what am i missing?
    why do u even need etc/config.xml file?
    this is not extension and if it was you are missing app/etc/modules/*.xml file to enable it.
    wouldn’t it be better to keep it separately so you dont populate webpage repo with tests? i guess that you dont want to deploy tests to live environment

    • Johann Reinke says:

      Hi,
      File structure respects Magento file structure but you’re right this is not a real module since it does not need to be enabled to run tests.
      Of course you can separate test files as you wish, that’s what I did with CasperJS for example.
      Take this as an example of use, not for what you must do.

  4. Hello,
    Thankyou for this tutorial. How would I click a radio button using this extension? I see a number of ways to do it w/ Mink posted, but none of them appear to work with this extension. Please advise.
    thanks!
    tk

  5. Kevin says:

    Hi,

    I noticed the repo hasn’t been updated in 2 years. Is this still the best functional testing tool for Magento?

  6. Manuel says:

    Hi,

    Short question…

    Scenario:
    1 Magento core has 3 websites.

    Question:
    How to test other websites? only the default website is being tested.

    Great tutorials thanks!

Leave a Reply

* Required fields

Categories