ニュース・ブログ

ニュース・ブログ一覧PHPの記事情報PHP unit testing integration in cakephp

PHP unit testing integration in cakephp

One of the modern best practices in software engineering and application development, is to perform unit testing. Unit testing, test small units of our Application. In short we can say to eliminate bugs and errors, for preventing registration we can use unit testing.

For unit test we have to follow below steps 

  • Input
  • Output
  • Match with our expected result.

PHP unit testing implementation in cakephp is easy! We can test the cakephp controller, table, entity, helper, component, behavior and so on. Let’s see the steps on how we can implement unit tests in cakephp.

Step 1: Installation PHPUnit in cakephp.

Good news is if you are using cakephp version> 3.5, the PHP unit should already be installed with your cakephp skeleton. You can check the  composer.json file . Where in the require-dev section PHP unit has been included.  

If you are not able to see the location vendor / phpunit folder , then you have to install it by composer. 

$ php composer.phar require –dev phpunit / phpunit: “^ 8.5”

Step 2: Creation test database connection for unit testing. 

  • First create a database like your production database without tables. 
  • For connection go in config / app.php Or config / app_local.php , there is a section called Datasources . In the` Datasources` section there are two connections. That you will see one is default , another is test . You have to connect your test database in the test section. Example given below.
    ‘test’ => [
           ‘host’ =>’localhost’,
            //’port’ =>’ non_standard_port_number’,
            ‘username’ =>’root’,
            ‘password’ =>’secret’,
            ‘database’ =>’test_myapp’,
             //’schema’=>’myapp’,
             ‘url’ => env (‘DATABASE_TEST_URL’, null),
    ] ,,,

Step 3: Creating fixtures for unit testing. 

  • Using fixtures usually we will do two things 

–How will our test table be created?

–Which records initially will be populated to the table? 

We can use the cake bake command to generate fixtures from our existing production database. 

Example: Example: 

–bin / cake bake fixture users

After give this command a fixture will be create in `tests / Fixture / UsersFixture.php`

After open UsersFixture.php we should see two things 

1. Our test table structure.

2. An initialised test record based on table structure, which is automatically generated by cakephp bake command.

Example of our tests / Fixture / UsersFixture.php will like below

<? php
declare (strict_types = 1);
namespace App \ Test \ Fixture;
use Cake \ TestSuite \ Fixture \ TestFixture;
class UsersFixture extends TestFixture
{
       public $ fields = [
                    ‘id’ => [‘type’ =>’integer’,’length’ => null,’unsigned’ => false,’null’ => false,’default’ => null,’comment’ =>” ,’autoIncrement’ => true,’precision’ => null],
                   ‘username’ => [‘type’ =>’string’,’length’=> 100,’null’ => false,’default’ => null,’collate’ =>’utf8_general_ci’,’comment’ => ”,’precision’ => null],
                   ‘email’ => [‘type’ =>’string’,’length’=> 100,’null’ => false,’default’ => null,’collate’ =>’utf8_general_ci’,’comment’ => ”,’precision’ => null],
                   ‘password’ => [‘type’ =>’string’,’length’=> 100,’null’ => false,’default’ => null,’collate’ =>’utf8_general_ci’,’comment’ => ”,’precision’ => null],
                   ‘created’ => [‘type’ =>’datetime’,’length’ => null,’precision’ => null,’null’ => false,’default’ => null,’comment’ =>” ] ,,,
                   ‘modified’ => [‘type’ =>’datetime’,’length’=> null,’precision’ => null,’null’ => false,’default’ => null,’comment’ =>” ] ,,,
                    ‘_constraints’ => [
                          ‘primary’ => [‘type’ =>’primary’,’columns’ => [‘id’],’length’ => []],
                     ] ,,,
                   ‘_options’ => [
                           ‘engine’ =>’InnoDB’,
                           ‘collation’ =>’ utf8_general_ci’
                   ] ,,,
          ] ;;
    publicfunctioninit (): void
   {
            $ this-> records = [
                 [
                     ‘id’ => 1,
                     ‘username’ =>’jon’,
                     ‘email’ =>’jon@test.com’,
                     ‘password’ =>’ a6677ccxxzkk && ## $$’,
                     ‘created’ => ‘2021-09-13 06:52:34’,
                     ‘modified’ => ‘2021-09-13 06:52:34’,
                 ] ,,,
            ] ;;
            parent :: init ();
      }
}

Step 4: Create a test for model / table for unit testing

Now we are ready to test our application. First let’s test a model / table. Where we will test a buildRules function. So, In table / UsersTable.php the method looks like below, where it’s a rule for making user email unique ..

public function buildRules ( RuleChecker $ rules )

 {

      $ rules- > add ( $ rules- > isUnique ([ ‘email’ ]));

      return $ rules ;

 }

Now at first we will create a test file for model / table / users , we can create it by below the bake command. The file will be located in folder tests / TestCase / Model / Table / usersTableTest.php

bin / cake bake test table users

By same way we can create test file for controller and entity 

bin / cake bake test entity user

bin / cake bake test controller users

All test files and folders will be created in the tests directory in our application.

After generate test files by cake bake our tests / TestCasse / Model / Table / usersTableTest.php files will looks like below

<? php
declare (strict_types = 1);
namespace App \ Test \ TestCase \ Model \ Table;
use App \ Model \ Table \ usersTable;
use Cake \ TestSuite \ TestCase;
class usersTableTest extends TestCase
{
          protected $ users;
          public function setUp (): void
          {
                  parent :: setUp ();
                  $ config = $ this-> getTableLocator ()-> exists (‘users’)? []: [‘className’ => usersTable :: class];
                  $ this-> users = $ this-> getTableLocator ()-> get (‘users’, $ config);
           }
            public function tearDown (): void
           {
                   unset ($ this-> users);
                   parent :: tearDown ();
            }
}

Note all test files will extends by TestCase class, it’s mandatory. Here we can see two method one is setUp () and another is tearDown (), tearDown () will executed before all action run, and tearDown () will execute after all action executed.

Now here we will write a test case method for our existing buildRules method. We have to always used the test keyword before all test functions, otherwise it will not execute when we run the test.
Example:

public function testBuildRulesEmail ()
{
           $ entity = $ this-> AdminUsers-> newEntity ([[[[[
                   ‘email’ =>’jon@test.com’
            ]);
            $ this-> assertFalse (
                     $ this-> AdminUsers-> checkRules (
                            $ entity
                       )
                )
            ;
          $ this-> assertSame (
                  [‘_isUnique’=>’This value is already in use’],
                  $ entity-> getError (‘email’)
          );
}

Now for testing our above function we have to use our fixture that we have created for our users table. We can load fixture in our UsersTableTest.php like below

public $ fixtures = [

       ‘app.Users’ ,

] ;;

Now our final  UsersTableTest.php  files will looks like

<? php
        declare (strict_types = 1);
        namespace App \ Test \ TestCase \ Model \ Table;
        use App \ Model \ Table \ usersTable;
        use Cake \ TestSuite \ TestCase;
      class usersTableTest extends TestCase
      {
           protected $ users;
           // load fixtures
           public $ fixtures = [
                ‘app.Users’,
           ] ;;
           publicfunctionsetUp (): void
          {
                parent :: setUp ();
               $ config = $ this-> getTableLocator ()-> exists (‘users’)? []: [‘className’ => usersTable :: class];
               $ this-> users = $ this-> getTableLocator ()-> get (‘users’, $ config);
           }
          publicfunctiontearDown (): void
          {
                unset ($ this-> users);
                parent :: tearDown ();
           }
           publicfunctiontestBuildRulesEmail ()
          {
                $ entity = $ this-> AdminUsers-> newEntity ([[[[[
                ‘email’ =>’jon@test.com’
               ]);
                $ this-> assertFalse (
                          $ this-> AdminUsers-> checkRules (
                                    $ entity
                            )
                       )
                ;
                $ this-> assertSame (
                        [‘_isUnique’=>’This value is already in use’],
                        $ entity-> getError (‘email’)
                 );
           }
}

Step 5: How to run this test case?

For Mac:

Vendor / Bin / Phpunit Tests / TestCase / Model / Table / UsersTableTest . Php 

For run all Tests ( controllers , tables , entity ) 

Vendor / Bin / Phpunit 

For Only model 

 Vendor / Bin / Phpunit Tests / TestCase / Model /

For windows:

change / to \

–vendor \ bin \ phpunit tests \ TestCase \ Model \ Table \ UsersTableTest.php

After run our test script by below command

–vendor / bin / phpunit tests / TestCase / Model / Table / UsersTableTest.php

Output should be:

OK (1 test, 2 assertions)