Before we begin
If you are unfamiliar with unit testing and specifically PHPUnit (the testing framework used by Magento) I suggest you read the https://phpunit.de/

Here we go.

Scenario: We have decided to extend the core Breadcrumbs block class with some additional functionality.

A basic first test would be that our new class extends the original class. We begin by creating a test class.

Unit tests within modules are located in app/code/[codePool]/[Vendor]/[ModuleName]/Test/Unit followed by a path reflective of the object you are testing.

E.g.

Our new class will eventually (but not yet) reside in app/code/[codePool]/[Vendor]/[ModuleName]/Block/Theme/Html/Breadcrumbs.php so you would have a test located app/code/[codePool]/[Vendor]/[ModuleName]/Test/Unit/Block/Theme/Html/BreadcrumbsTest.php

Note the Test suffix on the test class. !important

Create your test class.

In BreadcrumbsTest.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
<?php

namespace [Vendor]\[ModuleName]\Test\Unit\Block\Theme\Html;

class BreadcrumbsTest extends \PHPUnit_Framework_TestCase
{
    /** @var \[Vendor]\[ModuleName]\Block\Theme\Html\Breadcrumbs */
    protected $block;
    
    public function setUp()
    {
        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
        
        // we want this to be a real Magento 2 object
        // complete with all it's dependencies
        // so we use the object manager to get it
        $this->block = $objectManager
            ->getObject('[Vendor]\[ModuleName]\Block\Theme\Html\Breadcrumbs');
       
    }
    
    public function testMyBlockExtendsOriginal()
    {
        $this->assertInstanceOf('Magento\Theme\Block\Html\Breadcrumbs',
                                $this->block);
    }
}

[BriefPHPUnitLesson]

The class should look similar to any other class you create in Magento except that it extends \PHPUnit_Framework_TestCase (Line 5).

setUp()(Line 10) is not required but it is a good place to put generic initialization of class vars used in each test. Bare in mind this function is ran before every test in the class

Test names (functions) (Line 22) always begin with the keyword test. That is how PHPUnit knows to run it as a test. Test function names should always be verbose enough to describe what the test does.

[/BriefPHPUnitLesson]

Ok great but how do i run these tests?

Well, whilst in your project root directory do (but not actually run yet):

vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist

The -c dev/tests/unit/phpunit.xml.dist is a pointer to a PHPUnit configuration file shipped with Magento 2.

It tells phpunit what tests to run, how to run them etc.

It also specifies a suffix of Test.php which means it only looks for test files in the specified locations that have Test.php on the end. This is why it was important earlier to have BreadcrumbsTest.php

Magento however comes with many tests out the box and they take a long time to run. There is a way however to run just the tests in your new module by passing a path to your module after the configuration file like so;

vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist app/code/[codePool]/[Vendor]/[ModuleName]

Go ahead and run the above.

You should find an error occurs with output similar to:

PHPUnit 4.8.9 by Sebastian Bergmann and contributors.

E

Time: 128 ms, Memory: 13.25Mb

There was 1 error:

1) [Vendor]\[ModuleName]\Test\Unit\Block\Theme\Html\BreadcrumbsTest::testMyBlockExtendsOriginal
ReflectionException: Class [Vendor]\[ModuleName]\Block\Theme\Html\Breadcrumbs does not exist

...

FAILURES!
Tests: 1, Assertions: 0, Errors: 1.

No need to panic!

This is actually what we expect to see because we have not created our new Breadcrumbs class yet.

This is called a failing test and is considered best practice programming. You start with a failing test then you write code to make the test pass.

So in app/code/[codePool]/[Vendor]/[ModuleName]/Block/Theme/Html/Breadcrumbs.php:

<?php

namespace [Vendor]\[ModuleName]\Block\Theme\Html;

use Magento\Theme\Block\Html;

class Breadcrumbs extends Html\Breadcrumbs
{
    @todo Put your additional functionality here
}

Run your test again:

vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist app/code/[codePool]/[Vendor]/[ModuleName]

Bingo!

We have a passing test.

PHPUnit 4.8.9 by Sebastian Bergmann and contributors.

.

Time: 150 ms, Memory: 15.50Mb

OK (1 test, 1 assertion)

Why test my code?

Tests are a blueprint to what your code should do when implemented. If you were to make a change that had a side effect, your tests could pick this up before it goes live. Using a CI approach, tests can be run as part of the go live process and should they fail, the code would not go live until such time that they are passing again.

  • magento2

Like this post? Share it :)


Related Posts

Back