If you started out writing one page, simple scripts in PHP like I did. You probably were not thinking about testing your code before you lumped it onto the server.
I mean, it worked right? You were probably pretty confident about it, as I was.
As you have progressed in your development journey and moved towards more complex structurings of your code, such as with frameworks and multiple folder systems, I’m sure the default level of confidence in your codebase, when untested, that you started with, has begun to go down a peg.
It sure did for me.
As I improved as a developer, I wanted my code to do the same, so I began to look for the ways that I could be sure that my code was ‘good code’ or at least, it behaved as I expect it to.
The most important and reliable way I found that this could be done was by testing it.
Why Testing Code Is Important?
As you develop your code, what you are doing is creating a complex structure. If you imagine that this structure is real, like a building for example. You would want to make sure that the integrity of the structure is good (ie. that there are no bugs) so that it would not surprise you at any point, such as by collapsing.
In the real-world building process, you ensure this by engaging in various checks, tests, and surveys of structural integrity, done throughout the building process. When coding, you test. Specifically, you unit test
.
What is ‘Unit Testing’?
The word ‘unit’, within the context of code testing, refers to a block of code that will be tested.
Usually, this block is in the form of a class method, a function, or some other highly relevant, segmented block of code. Essentially it is a segment of code whose integrity and expected output we want to ensure.
As stated on the PHPUnit Wikipedia,
The goal of unit testing is to isolate each part of the program and show that the individual parts are correct. A unit test provides a strict, written contract that the piece of code must satisfy. As a result, unit tests find problems early in the development cycle.
What Does ‘Testing Code’ Mean?
Testing code in general is the process of identifying, breaking down, and then specifying the units of our code that we would like to test. We do this by outlining our expected outcome. And then once we’ve done that, running those units through tests, using testing software tools to see if our expected outcomes are what we get.
All programming languages, in their ecosystem, dispose of some kind of toolings used to unit test source codes. PHP is not of an exception. And we have tools like PHPUnit, Codeception, Behat, PHPSpec, Storyplayer, Peridot, and much more out there.
In this post, we will focus on how you can get started with PHPUnit.
PHPUnit
If you’ve been involved in the PHP community for some time now, you’ve most likely heard of PHPUnit. It’s not only one of the most popular unit testing frameworks in PHP but is also one of the easiest to use.
Testing our code with PHPUnit is simply a matter of placing and applying our units of code within tests. These units are tested by writing a unique ‘test cases’.
How To Use PHPUnit - Step By Step
The typical testing flow goes like this:
- Import the class method, function, or segment of code to test. The
unit
you want to test. - Give input to the function, method, or unit.
- Define what to expect as the output of the unit.
- Check if the function/method/unit produces the expected output.
Installing and using PHPUnit
To get started testing with PHPUnit, we first need to start by installing it. There are two ways of using PHPUnit.
1- As a local development-time dependency: Basically you will add PHPUnit with composer as a development dependency. The advantage of using it that way is that you can easily migrate from one version to another, and you can use a different version for two distinct projects.
2- As an installed tool in your development machine. This allows you to have a globally installed tool that can be used throughout your machine regardless of the project.
You can refer to the official installation guide for more details on these two ways of installation. For the brevity of this post, we will focus only on the first method.
To do so, first, navigate to or create the folder within which our project will sit(Example
in my case), and then we can download(add to our dependencies) PHPUnit with the following command:
composer require --dev phpunit/phpunit
Creating Our Class (Which We Will Then Test)
Once we’ve downloaded PHPUnit into our folder, we can now begin our testing process by first writing the class that we will be testing. Let’s create a simple ‘User’ class that sets a $first_name
and a $last_name
property. And then has a function that returns the combination of these two properties as a full name
.
You can see an example of this below(User.php):
<?php
final class User
{
public $first_name;
public $last_name;
public function getFullName(): string
{
return $this->first_name . " " . $this->last_name;
}
}
Creating The Test Folder & phpunit.xml
Once we have set up our ‘User’ class, let us now set up our ‘tests’ folder, where we will hold our tests.
We will also create our phpunit.xml
file at the root of our project. We will reference the folder where our tests are held inside that file. We do this by placing the name of the folder in the directory element within our XML file.
Here is a minimal content one could have on your phpunit.xml file:
<phpunit bootstrap="vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="IntroPHPUnitTest">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
Writing Our First Test
Now that we have created our tests/ folder, we may now move onto creating our first test. In this, we will be simply checking if our getFullName()
class method above returns a string of $first_name
and $last_name
as we expect.
Our test will look like this(UserTest.php):
<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class UserTest extends TestCase
{
/*
Our first test method: testing if our
User class can return a full name
*/
public function testReturnsUserFullName()
{
// We need to bring in our User class
// so that we can access its methods
require_once './User.php';
// Get an instance of the User class
$user = new User;
// Set the properties
$user->first_name = 'Femy';
$user->last_name = 'Babatunde';
// Assert if the getFullName() can return the full name 'Femy Babatunde'
$this->assertEquals('Femy Babatunde', $user->getFullName());
}
}
Here we are including the ‘TestCase’ class from PHPUnit, which gives us the functionality that we need to run the test.
Then we create our test class UserTest
which extends the TestCase
class from PHPUnit.
Bear in mind that the name of the test file should ideally have the name of the class to be tested, suffixed with the term ‘Test’ such as the above specified UserTest
class definition.
The name of the method that we use to wrap our actual unit test should be as much as possible, a description of the test that we are attempting to run. In the above case, it is testReturnsUserFullName
, which is what our test checks for.
Inside this method, we then load in and instantiate our original class, our data, and then attempt to run our test using the assertEquals($expected, $actual)
method from PHPUnit. The method checks if its two arguments match. That is to set the full name, using our $first_name
and $last_name
properties that we defined within our constructor.
Once we have set up our test assertion, we are now ready to run our test.
Running Our First Test
Overview of our project
Once we have created our test, it is now time for us to run it. But, before we move on to testing our setup, let's have a look at how our project looks like.
PHPUnit's framework in actually inside a subfolder named bin
located in the vendor
folder.
If you installed PHPUnit using our second method of installation above, you may do this by simply running the command phpunit
in our command line, while within the folder directory where we have installed PHPUnit. But, in our case, we used the first method to install PHPUnit as a project-level dependency. So, to run your test type the following command while being in the root folder, Example
:
.\vendor\bin\phpunit
The expected output of the above test case within the command line should let you know that the test passed. This is how it looks like in my case:
With a “Passed” statement and no “Failed” statements, this means that our tests have passed and that our assumption for the test (or test cases) is validated.
Wrapping It All Up
This is what testing in PHP using PHPUnit looks like. This example used here is a very basic use case. You push further with more complex code. Please, refer to the official PHPUnit website for more on the subject.
In other languages, the general idea is also the same. Ultimately, all tests of code follow the same structure that we’ve outlined above.
I hope that this tutorial has given you enough information to get you started with unit testing in PHP and unit testing in general.
Last updated 2024-01-11 UTC