Foreword
Hello everyone, I am back here. I have joined many projects of the company so far, from projects without installing CI / CD to projects integrating CI / CD into projects. A nice day join a project that is starting phase 2 already, suddenly I have just edited a little api but when pushing the code to the CI reported an error, opening the CI to check it saw no convention error, but again Fail test error message. At that time, it was so confusing, writing tests in Laravel was something, because up to now, my projects do not usually write tests, so I do not care about writing tests. And the writing test started. But then I realized that writing tests is quite important, I have considered writing this test as unnecessary, functional code so that it can run.
What is PHPUnit?
PHPUnit is one of the most well known and highly optimized unit testing packages, which is considered as the first choice of many programmers for fixing various application security vulnerabilities. Its main function is to perform all unit testing in the application. It supports most PHP frameworks including Laravel.
PHPUnit was developed with many simple assertion
, plus it gives optimal results when you test each function in your code. But the process of testing the controller, model and form validation can be more complicated than you might imagine.
Unit Test in Laravel
Laravel is a popular framework currently used by many programmers. From a testing perspective, it is also known to include testing when installing frameworks in use. In Laravel there are 2 ways to test, first with Unit testing
, second is Feature testing
. Unit testing allows us to test model classes, controllers, etc. The goal of Unit test
is to check the integrity of the code unit’s processing. Feature Testing allows you to test the API, test the results. returns, tests functionality, performance and load capacity of the application.
If you have already installed the Laravel init project, you can see two available subfolders. That is the tests
folder with 2 sub-folders that are the Unit
and Feature
used for writing tests here.
To clarify, I will give an example of writing unit tests in the next section.
For example unit tests in Laravel
Okay ok we will come up with an example for writing unit tests in a project using Laravel. In every Laravel project, there is already phpunit/phpunit
available so you just need to use it. And the first thing in writing tests is to create test classes. These classes are stored in the tests
directory of the Laravel project. And they have certain naming rules so that PHPUnit can find each of these test files and run them. For example, you can test the model you can set to UserTest.php
. Next you will see the TestCase.php
file which is located at the same folder as Unit
and Feature
. It is basically a file to set up the Laravel environment and the features inside our test. You mean that we will be able to use the functions that support us to write more tests, and those functions are what I will introduce to you in the process of making an example.
To create a test file you will use the command
1 2 | php artisan make <span class="token punctuation">:</span> test |
Let’s try to create a test file to see what it looks like
1 2 | php artisan make <span class="token punctuation">:</span> test UserTest <span class="token operator">--</span> unit |
And Laravel will generate for us a file with the following content:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">Tests Unit</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Tests TestCase</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Foundation Testing WithFaker</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Foundation Testing RefreshDatabase</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">UserTest</span> <span class="token keyword">extends</span> <span class="token class-name">TestCase</span> <span class="token punctuation">{</span> <span class="token comment">/** * A basic unit test example. * * @return void */</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">testExample</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">assertTrue</span> <span class="token punctuation">(</span> <span class="token boolean">true</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
The name of the test method must be meaningful for what you want to test, there are 2 ways to name the test function
- test_store_survey ()
- testStoreSurvey ()
And PHPUnit cannot run tests with protected
and private
methods, so you have to modify the test function to be public. We can also easily find the phpunit.xml
file, PHPUnit will automatically locate the file name named in phpunit.xml
or phpunit.xml.dist
in the current executable directory. Within this file, we can specifically configure the execution of our test.
First of all, we will look through a bit of the functions mong đợi
our results to see if after running the test, it looks like that. You can use 7 PHPUnit assertion functions to look forward to your output
- assertTrue ()
- assertFalse ()
- assertEquals ()
- assertNull ()
- assertContains ()
- assertCount ()
- assertEmpty ()
assertTrue () and assertFalse ()
These two functions are intended to allow us to expect after a process of running the test is completed true or false
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 | <span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">Tests Unit</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Tests TestCase</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Foundation Testing WithFaker</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Foundation Testing RefreshDatabase</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">App User</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">UserTest</span> <span class="token keyword">extends</span> <span class="token class-name">TestCase</span> <span class="token punctuation">{</span> <span class="token comment">/** * A basic unit test example. * * @return void */</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">test_has_user</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$users</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">User</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'Lena'</span> <span class="token punctuation">,</span> <span class="token single-quoted-string string">'Misa'</span> <span class="token punctuation">,</span> <span class="token single-quoted-string string">'Leona'</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">assertTrue</span> <span class="token punctuation">(</span> <span class="token variable">$users</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">has</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'Lena'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">assertFalse</span> <span class="token punctuation">(</span> <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">has</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'Minh Minh'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
To run phpunit you run the following command
1 2 | <span class="token punctuation">.</span> <span class="token operator">/</span> vendor <span class="token operator">/</span> bin <span class="token operator">/</span> phpunit |
then you will see the results returned as this has successfully run the test
1 2 | <span class="token constant">OK</span> <span class="token punctuation">(</span> <span class="token number">2</span> tests <span class="token punctuation">,</span> <span class="token number">4</span> assertions <span class="token punctuation">)</span> |
assertEquals () and assertNull ()
assertEquals()
helps us compare the true value after a processing sequence with the value we want.
assertEmpty()
helps us check if the desired value is null
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 28 29 30 31 32 33 34 | <span class="token keyword">namespace</span> <span class="token package">Tests Unit</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Tests TestCase</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Foundation Testing WithFaker</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Foundation Testing RefreshDatabase</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">App User</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">UserTest</span> <span class="token keyword">extends</span> <span class="token class-name">TestCase</span> <span class="token punctuation">{</span> <span class="token comment">/** * A basic unit test example. * * @return void */</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">test_has_user</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$users</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">User</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'Lena'</span> <span class="token punctuation">,</span> <span class="token single-quoted-string string">'Misa'</span> <span class="token punctuation">,</span> <span class="token single-quoted-string string">'Leona'</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">assertTrue</span> <span class="token punctuation">(</span> <span class="token variable">$users</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">has</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'Lena'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">assertFalse</span> <span class="token punctuation">(</span> <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">has</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'Minh Minh'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">test_equal</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$expected</span> <span class="token operator">=</span> <span class="token double-quoted-string string">"Hoang"</span> <span class="token punctuation">;</span> <span class="token variable">$actual</span> <span class="token operator">=</span> <span class="token double-quoted-string string">"Min Hoang"</span> <span class="token punctuation">;</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">assertEquals</span> <span class="token punctuation">(</span> <span class="token variable">$expected</span> <span class="token punctuation">,</span> <span class="token variable">$actual</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"actual value is not equals to expected"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
And results
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | PHPUnit <span class="token number">8.2</span> <span class="token number">.5</span> by Sebastian Bergmann <span class="token keyword">and</span> contributors <span class="token punctuation">.</span> F <span class="token number">1</span> <span class="token operator">/</span> <span class="token number">1</span> <span class="token punctuation">(</span> <span class="token number">100</span> <span class="token operator">%</span> <span class="token punctuation">)</span> Time <span class="token punctuation">:</span> <span class="token number">64</span> ms <span class="token punctuation">,</span> Memory <span class="token punctuation">:</span> <span class="token number">10.00</span> <span class="token constant">MB</span> There was <span class="token number">1</span> failure <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">)</span> UserTest <span class="token punctuation">:</span> <span class="token punctuation">:</span> test_equal actual value is not equals to expected Failed asserting that two strings are equal <span class="token punctuation">.</span> <span class="token operator">--</span> <span class="token operator">-</span> Expected <span class="token operator">++</span> <span class="token operator">+</span> Actual @@ @@ <span class="token operator">-</span> <span class="token single-quoted-string string">'Hoang'</span> <span class="token operator">+</span> <span class="token single-quoted-string string">'Min Hoang'</span> <span class="token constant">FAILURES</span> <span class="token operator">!</span> Tests <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">,</span> Assertions <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">,</span> Failures <span class="token punctuation">:</span> <span class="token number">1.</span> |
You try to change $expect = 'Hoang'
again, the output is right now
1 2 | <span class="token constant">OK</span> <span class="token punctuation">(</span> <span class="token number">3</span> tests <span class="token punctuation">,</span> <span class="token number">6</span> assertions <span class="token punctuation">)</span> |
assertContains (), assertCount () and assertEmpty () We will learn together with 3 assertion functions that work with arrays.
assertContains()
: this function is intended whether the value exists or the provided array contains the value we expect.assertCount()
: This function expects the number of items in an array of results to match the quantity we want.assertEmpty()
: This function expects the resulting array to be empty.
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 | <span class="token keyword">namespace</span> <span class="token package">Tests Unit</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Tests TestCase</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Foundation Testing WithFaker</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Foundation Testing RefreshDatabase</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">App User</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">UserTest</span> <span class="token keyword">extends</span> <span class="token class-name">TestCase</span> <span class="token punctuation">{</span> <span class="token comment">/** * A basic unit test example. * * @return void */</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">test_contain_princess</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$princesses</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'Linda'</span> <span class="token punctuation">,</span> <span class="token single-quoted-string string">'Lisa'</span> <span class="token punctuation">,</span> <span class="token single-quoted-string string">'Celindar'</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">assertCount</span> <span class="token punctuation">(</span> <span class="token number">3</span> <span class="token punctuation">,</span> <span class="token variable">$princesses</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">assertContains</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'Linda'</span> <span class="token punctuation">,</span> <span class="token variable">$princesses</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">assertEmpty</span> <span class="token punctuation">(</span> <span class="token variable">$princesses</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
You will get the result of pass 2 test and fail the last test because $princesses
not empty.
How to know if writing unittest is satisfactory?
We write a satisfactory unittest when all three of the following are met:
- Arrange: set the emulation state, initialize the Object, mock Mock
- Act: Run the correct method we are testing
- Assert: Compares the expected result with the result returned.
Conclude
Through some of our share, we have also learned the most basic things about UnitTest, the next section I will write about a specific example of writing UnitTest for the CRUD resource functions that we often use. write in the controller. Thank you for reading my shared article