RUN UNIT TESTING IN MAGENTO 2

Unit Testing

Unit Testing is a method for software testing in the scope of which individual units (function, method in a class), their associated data, usage, and operations are tested to determine if these are working as designed.

As this is based on individual unit testing, there is no coupling among units, and that is very easy to test because it avoids complications.

Benefits Of Unit Testing:

Easy to Debug:

Unit testing finds problems early because it isolates each part of the program and shows that individual parts are correct. This includes debugging the program logic and flaws or missing parts of the specification for the unit.

Quality of Code:

As unit testing identifies the bugs at the program level, it improves code quality. It restricts programmers from following the standard to fix the bugs.

Make Program Easy to Change/Upgrade:

Unit testing makes it easy for the programmer to refactor/upgrade the code later. In addition, it creates a high cohesion among programs and makes sure the module works correctly even after changes or upgradation.

Design Accuracy:

Unit testing restricts programmers from following the code standards to focus on specifications for the unit. To fulfill the specifications of a unit, unit testing forces the programmer to think about design too, which makes the design more accurate.

Reduce Costs:

Unit testing helps to find and fix the bugs at an early stage, reducing the cost and saving time to debug the modules later. In addition, it reduces the complexity during System Testing and makes everything smooth in development.

Implementing Unit Testing In Magento 2

Magento 2 has been launched with PHPUnit pre-installed, an automated testing framework for PHP. It has been included as a dependency in Magento 2. So, here is the custom module that will help you understand the basic implementation of Unit Testing. You will see the custom module to check a given string should be alphabetical.

Following are the steps:

Create And Register A New Custom Module

To create a custom module, the first step is to create a file, module.xml in folder, <Magento Root Folder>/app/code/<Vendor Name>/<Module Name>/etc/ folder. Let’s take the path –

/app/code/Bizspice/UnitTesting/etc/module.xml

and paste the following code into this file:

<?xml version="1.0" ?> 
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">             
<module name="Bizspice_UnitTesting" setup_version="1.0">   
</module> 
</config>

Now, create a file registration.php in /app/code/Bizspice/UnitTesting/ folder with the following code:

<?php 
\Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE,      
'Bizspice_UnitTesting',
      __DIR__
  ); 

Create Model File

Create Alphabet.php under /app/code/Bizspice/UnitTesting/Model folder with the following code:

<?php
  namespace Bizspice\UnitTesting\Model;
    class Alphabet {
      /**
       * this function will accept and return the string
       *        
* @param string str
       * @return string       
*/
      public function getText($str) {
          if(preg_match("/^[a-zA-Z][a-zA-Z ]*$/", $str)){
              return $str;           
}else{
  return false;
      } 
 } 

Here, you can see the getText() function, which checks the string and whether it contains only alphabets or not.

Create Test File:

Now, create a file to test getText() function. Create AlphabetTest.php under  /app/code/Bizspice/UnitTesting/Test/Unit/Model/ folder with the following code:

<?php
  namespace Bizspice\UnitTesting\Test\Unit\Model;
    class AlphabetTest extends  \PHPUnit\Framework\TestCase {
        protected $_objectManager;
      protected $_desiredResult;
      protected $_actualResult;
      protected $_alphabet;
      protected $_text;
        /**        
* used to set the values to variables or objects.       
*        
* @return void        
*/       
public function setUp() { 
         $this->_objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
          $this->_alphabet = $this->_objectManager->getObject("Bizspice\UnitTesting\Model\Alphabet"); 
      }      
/**       
* this function will check if string is having alphabets only
      */      public function testGetText() {
           $this->_actualResult = $this->_alphabet->getText("This is my testing string");
           $this->_desiredResult = "This is my testing string";
           $this->assertEquals($this->_desiredResult, $this->_actualResult); 
      } 
} 

All test files must be named with Test.php as a suffix because it has to be mentioned in the phpunit.xml file. You will see it below soon.

Also, the path of the test files must be the mirror of the files to be tested. For instance, we have created /app/code/Bizspice/UnitTesting/Model/Alphabet.php, so the test file must be located at /app/code/Bizspice/UnitTesting/Test/Unit/Model/AlphabetTest.php.

Enable Module

To test a function/method, its corresponding module must be enabled. So, open the terminal, go to your Magento directory and run the following commands to enable the module:

rm -rf pub/static/* var/* generated/*;
chmod 0777 var/ pub/ generated/;
chmod 0777 -R var/ generated/ pub/;
php bin/magento setup:upgrade php bin/magento setup:di:compile 
php bin/magento setup:static-content:deploy -fphp bin/magento indexer:reindex
php bin/magento cache:clean
php bin/magento cache:flush

phpunit.xml

After enabling the module, now it has to be tested. Actually, Magento 2 has made testing very easy, and the <root folder>/dev/tests/unit/phpunit.xml.dist file has to be managed for this.

Rename this file to phpunit.xml and open this file. Go to <testsuite name=”Magento Unit Tests”> tag:Add the following line to the testsuite tag:

<directory suffix=”Test.php”>../../../app/code/Bizspice/UnitTesting/Test/Unit</directory>

As attribute suffix denotes fetch all files having suffix Test.php and existing under /app/code/Bizspice/UnitTesting/Test/Unit directory and operate them.

To make testing faster, let’s comment on other lines under the testsuite tag as per follows:

That’s it! Now you are ready to start Unit Testing.

Unit Testing

To run the test, open terminal and go to your Magento directory and run the following commands:

  • cd dev/tests/unit
  • php ../../../vendor/phpunit/phpunit/phpunit

It will give you the following output:

Here, you will see that the test has been done successfully as a string with only alphabets passed in the testGetText() function in /app/code/Bizspice/UnitTesting/Test/Unit/Model/AlphabetTest.php

public function testGetText() {
        $this->_actualResult = $this->_alphabet->getText("This is my testing string");
        $this->_desiredResult = "This is my testing string";
        $this->assertEquals($this->_desiredResult, $this->_actualResult);
  
}

Now, to get the failure result, let’s change the string passed in the above function and replace the function with the following code:

public function testGetText() {
 
    $this->_actualResult = $this->_alphabet->getText("This is my testing string2222");
  $this->_desiredResult = "This is my testing string";
     $this->assertEquals($this->_desiredResult, $this->_actualResult);
 
}

Run the following command in the terminal again:

php ../../../vendor/phpunit/phpunit/phpunit

And you will see the following result:

Assertions For Testing

So, you have seen the basic implementation of Unit Testing. There a function assertEquals has been used in the testGetText() function in /app/code/Bizspice/UnitTesting/Test/Unit/Model/AlphabetTest.php. This is an assertion to compare the result for testing.

Following are a few types of Assertions:

assertTrue($x) Fail if $x is false 

assertFalse($x) Fail if $x is true 
assertNull($x)  Fail if $x is set 
assertNotNull($x)   Fail if $x not set 
assertIsA($x, $t)   Fail if $x is not the class or type $t 
assertNotA($x, $t)  Fail if $x is of the class or type $t 
assertEqual($x, $y) Fail if $x == $y is false 
assertNotEqual($x, $y)  Fail if $x == $y is true 
assertWithinMargin($x, $y, $m)  Fail if abs($x - $y) < $m is false 
assertOutsideMargin($x, $y, $m) Fail if abs($x - $y) < $m is true 
assertIdentical($x, $y) Fail if $x == $y is false or a type mismatch 
assertNotIdentical($x, $y)  Fail if $x == $y is true and types match 
assertReference($x, $y) Fail unless $x and $y are the same variable 
assertClone($x, $y) Fail unless $x and $y are identical copies 
assertPattern($p, $x)   Fail unless the regex $p matches $x 
assertNoPattern($p, $x) Fail if the regex $p matches $x 
expectError($x) Fail if matching error does not occour 
expectException($x) Fail if matching exception is not thrown 
ignoreException($x) Swallows any upcoming matching exception 
assert($e)  Fail on failed expectation object 

If you are curious to know more about Unit Testing, check this link (https://phpunit.de/)