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 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
<? phpdeclare (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
<? phpdeclare (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
<? phpdeclare (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 fixturespublic $ 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)
Written By: Alimon Karim Pito