How Do Developers Test Their Own Code? – Unit Testing
When we develop any application, testing is a major part of the development. After development, functionality testing is crucial as it can easily help identify any flaws in the code.
After you are sure your code works well as per requirements, you can integrate it with the system and perform integration tests to make sure it works with the other units too.
Developers are often faced with a challenge where the methods may be easy, but the application doesn’t work because of a small bug.
Now imagine, that you have a system with hundreds of methods, and suddenly a bug appears, and you need to track it and resolve it.
This might take a very long time. It is in situations like this that Code testing and Unit testing in a particular section can help prevent this type of problem.
So today we are going to discuss it in detail with the PHP development framework Laravel. In fact, the Laravel framework is also a PHP Unit testing framework itself.
PHP Unit is one of the most popular and widely useful testing frameworks. PHP Unit allows us to create both kinds of testing-Unit testing and Functional Testing.
We will learn the introduction of Unit and functional testing. Now, we’ll learn how to develop unit testing and functional testing in Laravel.
Unit and Functional Tests
If you already know about PHP Unit testing, we can divide testing into two different sections- Unit Testing and Functional Testing.
1. Unit Testing
- It is testing where you can test individual units/components of a developed functionality. The main aim is to work on each module as per the requirement of the client.
- It is the most important part of testing. Using fill up the input forms and generate a single output of testing. More importantly, you test a single piece of your code’s logic at a given time.
2. Functional Test
- It is the process of testing the functionality of a quality assurance process and a black-box type testing that bases the specifications of the software component test as per its use cases.
- Functions are tested by filling up the form inputs and verifying the output, and the internal program structure is mostly considered.
Let’s have a quick look at the below Example that’s an ideal case for Unit Testing.
public function getPostTitle($value)
{
return ucfirst($value);
}
- As you can see, the method does one and only one thing. It uses the ucfirst function to get the title, title first character is convert into uppercase.
- The unit test is used to test the correctness of a single logical unit of code. The functional test, on the other hand, allows you to test the correctness of a specific use case. More specifically, it allows you to simulate actions that a user performs in an application in order to run a specific use case.
- Let’s create an example that demonstrates how to create unit and functional testing in Laravel.
Setting Up the Obligatory
Before we go ahead and create an actual test, we need to set up a couple of things that will be used in software testing. We will create Posts modal and related migration.
Go ahead and run the below command in the terminal.
$php artisan make:model Posts –migration
- The above command should create the Posts model class and an associated database migration as well.
- The Posts model should look like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Posts extends Model
{
//
}
- And the database migration file should be created atdatabase/migrations/YYYY_MM_DD_HHMMSS_create_posts_table.php.
- The migrations should look like this:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(‘posts’, function (Blueprint $table) {
$table->increments(‘id’);
$table->string(‘post_name’);
$table->timestamps();
});
}
/**
* Reverse the migrations.
* @return void
*/
public function down()
{
Schema::dropIfExists(‘posts’);
}
}
- As above example, i have added one line $table->string(‘post_name’);. That line store post title name. Now just run to the migration command to create the post table.
$php artisan migrate
- Now we replace the below code in the Posts model.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Posts extends Model
{
/*
get post title name convert, first character in Uppercase
*/
public function getPostTitle($value)
{
return ucfirst($value);
}
}
- We have just added the accessor method, which modifies the title of the post, and that’s exactly what we will test in our unit test case. That’s it, as far as the Posts model is concerned.
- Next, we will create the Controller file in ‘app/Http/Controllers/PostController.php‘. It’ll be useful to us when we create the functional test case at a later stage.
<?php
// app/Http/Controllers/PostController .php
namespace App\Http\Controllers;
use App\Posts;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
public function index(Request $request)
{
// get the post-id from request params
$post_id = $request->get(“id”, 1);
// load the requested post
$post = Posts::find($post_id);
// check the name property
return ($post)?$post->name:”No Data”;
}
}
- In the above controller ‘index‘, retrieve the post id from the request parameters and try to load the post model object.
- Let’s add the route as well in the ‘route/web.php‘ file.
Route::get(‘posts/index’, ‘PostController@index’);
- And with that in place, you can run the http://your-laravel-site.com/posts/index URL to see if it works as expected.
Unit Testing
In the precedent section, we did the initial setup that’s going to be useful to us in this and upcoming sections. In this section, we are going to create an example that demonstrates the concepts of unit testing in Laravel.
- Laravel provides an artisan command that always creates the base template class of unit case.
- Run the above command to create the ‘PostsTest’ unit test case class. It’s important to note that we’re passing the –unit keyword that creates the unit test case, and it’ll be placed under the tests/unit directory.
$php artisan make:test PostsTest –unit
- And that should create the following class at ‘tests/Unit/PostsTest.php‘
<?php
namespace Tests\Unit;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class PostsTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
$this->assertTrue(true);
}
}
- Let’s replace it with some meaningful code.
<?php
namespace Tests\Unit;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use DB;
use App\Posts;
class PostsTest extends TestCase
{
public function testAccessorTest()
{
// load post manually first
$db_post = DB::select(‘select * from posts where id = 1’);
$db_post_title = ucfirst($db_post[0]->name);
// load post using Eloquent
$model_post = Posts::find(1);
$model_post_title = $model_post->name;
$this->assertEquals($db_post_title, $model_post_title);
}
}
- In the ‘testAccessorTest‘ method, we’re supposed to test the correctness of the ‘getPostTitle‘ method of the Posts model.
- For this, we have fetched a post from the database and prepared the expected output in the ‘$db_post_title‘ variable. Next, we load the same post using the Eloquent model that executes the ‘getPostTitle‘ method as well to prepare the post title. Finally, we use the assertEquals method to compare both variables as usual.
- So that’s the process of how to prepare unit test cases in the Laravel framework.
Functional Testing
- In this section, we will create the functional test case that tests the functionality of the controller that we have created.
- Now we run the below command and create the ‘PostsTest‘ functional test case class. As we not using the unit keyword, it will work as a functional test case and be placed under the ‘tests/Feature‘ directory.
$php artisan make:test PostsTest
- It will create the following class in ‘tests/Feature/PostsTest.php‘.
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class PostsTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
$this->assertTrue(true);
}
}
- Let’s replace it with some meaningful code.
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use DB;
class PostsTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testBasicTest()
{
// load post manually first
$db_post = DB::select(‘select * from posts where id = 1’);
$db_post_title = ucfirst($db_post[0]->name);
$response = $this->get(‘/posts/index?id=1’);
$response->assertStatus(200);
$response->assertSeeText($db_post_title);
}
}
- Firstly, we are fetching the title from the database and preparing the expected output in the ‘$db_post_title‘ variable. Following that, we try to simulate the ‘/posts/index?id=1‘ GET request and grab the response of that request in the $response variable.
- Next, we check the response code in the $response variable with the response code. In this case, it should be 200 so that we can get a valid response for our GET request. Further, the response should contain a title that starts with uppercase, and that’s exactly what we’re trying to match using the assertSeeText method.
- Now we have done everything we could run our tests against. Let’s now run the below command in the root of your application to run all tests.
$phpunit
- The above command will run all tests in your application. You should see standard PHPUnit output that displays the status of tests and assertions in your application.
Test Result
- If you get the 200 valid responses in GET Request, the below output will be the command line.
PHPUnit 6.5.14 by Sebastian Bergmann and contributors.
.. 2 / 2 (100%)
Time: 140 ms, Memory: 16.00MB
OK (2 tests, 3 assertions)
- If the code fails during test cases, you will get the below output.
i.e. I have changed the in a file at ‘tests/Unit/PostsTest.php‘. Just replace the code ‘$db_post = DB::select(‘select * from posts where id = 2′);’ in place of ‘$db_post = DB::select(‘select * from posts where id = 1′);’ and run command ‘phpunit‘. You will get the test results below.
PHPUnit 6.5.14 by Sebastian Bergmann and contributors.
.F 2 / 2 (100%)
Time: 115 ms, Memory: 16.00MB
There was 1 failure:
1) Tests\Unit\PostsTest::testAccessorTest
Failed asserting that two strings are equal.
— Expected
+++ Actual
@@ @@
-‘Post 2′
+’Post 1’
/var/www/html/your-laravel-site-folder/tests/Unit/PostsTest.php:24
/usr/share/php/PHPUnit/TextUI/Command.php:206
/usr/share/php/PHPUnit/TextUI/Command.php:162
FAILURES!
Tests: 2, Assertions: 3, Failures: 1.
So, this is all about unit testing, here we have to share How Laravel developers test their own code and how it can help you to better manage and control projects. As part of IT Staff Augmentation, developers leverage the technique of Unit Testing to ensure that their code works as intended by validating individual components and functionalities in isolation. If you have any confusion regarding this please contact our expert at OneClick.