Writing unit tests in PHP using PHPUnit
Let’s start with the term “unit testing”.
What is unit testing?
Wikipedia says:
In computer programming, unit testing is a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use.
It might seem a bit confusing. In simple terms, unit testing is the process of writing tests for individual parts of a program. So unit tests are tests written by software developers to ensure that the particular sections of a program (known as the ‘unit’) are behaving as intended.
The word unit can have different meanings in different types of programming:
- In procedural programming, a unit is often an individual function or procedure.
- In object-oriented programming, a unit could be a class and some consider it as a method.
Before writing any kind of test for your application you might be wondering “Does writing unit test help my application?”, and I should say YES, it’s so much beneficial.
Advantages
- Problems can be found early in the development cycle
- Problems like bugs, flaws or missing parts of the unit can be identified
- Writing test forces the developer to think about inputs, outputs, and error conditions, and therefore he/she can write better code
- Finding the bugs before or during developing an application is much lower than the bugs found after the release
- Poorly written units will make the process of unit testing hard if not impossible, so writing unit tests will force developers to structure their code in better ways
- After changing parts of our code in a big project unit testing make it so much easy to trace the exact location of the faults or failures
Disadvantages
- These unit tests won’t catch every error or bug in the program, because unit testing is only testing the functionality of the individual part of a program (‘unit’)
- Writing tests takes a long time
- Some problems cannot be tested
How can we write unit tests in PHP?
There are several ways to write unit tests, but the most commonly used way is using PHPUnit.
What is PHPUnit?
In general, PHPUnit is a unit testing framework for the PHP language. The main idea behind this framework is that every developer must be able to find mistakes and errors preventing it to get to be bigger and bigger.
How can we use PHPUnit?
1. Installing PHPUnit with Composer
We can easily add PHPUnit in our project using Composer:
composer require --dev phpunit/phpunit ^8
To make sure we have PHPUnit in our project we can use this command (You must run this command in your projects root directory):
./vendor/bin/phpunit --version
2. Adding an XML configuration file
There are a lot of command-line options to execute a test with customized features, but if you want to customize a lot of default behaviors then adding an XML config file can be helpful.
To do so add an XML file named phpunit.xml in the root directory of the project. Then we should add relevant XML tags to customize the tests.
This is a simple phpunit.xml config file indicates that:
colors=“true”
PHPUnit will print the output in different colors like red for errors, green for showing success, etc.stopOnFailure=“false”
It won’t stop if there will be a bug or error. (It means every test will be executed regardless of their output)bootstrap=”vendor/autoload.php”
It ensures that the source code and packages which have been install using Composer will be loaded automatically before any test will be executedname=”Calculator”
It gives our tests a name<directory>tests</directory>
It specifies the location of the test files (which is in our case the tests folder)
3. Using PSR-4 for autoloading
- Open the Composer.json file and add the autoload part like this:
The APP\\
says that the namespace we’re using will be App
and app
will use the app
directory for autoloading files.
2. Next, you should run this command:
composer update
With using this command your composer.json file configuration will be implemented.
4. Start writing your first test
First, some rules must be implemented:
- The test class must be named like
<prefix>Test
for exampleMyFirstTest
- The test class file name must be the same as the class name
- Every class must extend from the class
\PHPUnit\Framework\TestCase
- There should be at least one method (assertion) in a test class
- The test method name must start with the word
test
like‘testMyFunction’
- Create two folders and name them
app
and some rules musttests
Now your root directory must be like the picture above.
2. Now run this command in your command line: ./vendor/bin/phpunit
And this way you should get the message: ‘No tests executed!’
3. Go to the tests
folder and create a file called CalculatorTest.php
some rules must(As you can see the file name ends with ‘Test’) and again run PHPUnit: ./vendor/bin/phpunit
As you can see we have got a warning and that’s because we have no method in the CalculatorTest
class.
We’re going to write a test before writing its actual method which can be a good practice known as TDD (Test-driven development).
In general, in this methodology (TDD) developers write tests before writing the actual code which improves the code’s quality.
4. We’re going to write a method that gets an array of numbers and sums them all together and returns the final value. So let’s start writing its test.
Open the CalculatorTest.php
file and add this piece of code into it:
<?phpclass CalculatorTest extends \PHPUnit\Framework\TestCase
{public function testAdd()
{
$calculator = new App\Calculator;
$calculator->setOperands([5,20]);
$this->assertEquals(25, $calculator->add());
}
}
First of all, we create a public method called testAdd
after that, we will instantiate the App\Calculator
class (which doesn’t exist yet). Then we call the setOperands()
method from calculator
object and we pass an array of numbers.
On the last line of our code, we have called the assertEquals
method which is one of the PHPUnit built-in methods. It accepts two arguments and checks if they are equal.
Finally, we run PHPUnit to see if it works: ./vendor/bin/phpunit
Oh! We’ve got an error:
Error: Class 'App\Calculator' not found
Well, it’s right because we haven’t created the Calculator class yet!😉
5. Go to the app
folder and create the file Calculator.php
6. Open Calculator.php
and add this piece of code into it:
<?phpnamespace App;class Calculator
{
private $operands;public function setOperands(array $operands)
{
$this->operands = $operands;
}public function add()
{
return array_sum($this->operands);
}
}
In the code above we have two methods:
setOperands
This method receives an array of numbers and adds them to the operands
property in the class
add
This method is used to get the operands property and sum the numbers in it together and it finally returns the value.
After all, we run PHPUnit to see if it works: ./vendor/bin/phpunit
Yesss! It worked.
You might be asking yourself “what was $this->assertEquals()
?”. As we mentioned earlier it’s a built-in method of PHPUnit framework. But I’m here to say it’s not the only built-in function of this framework. Here are some of them:
assertEqual()assertNull()assertTrue()assertNan()assertLessThanOrEqual()assertClassHasAttribute()assertContains()assertIsWritable()
Each assert method accepts an optional argument which allows you to pass a custom error message:
$this->assertTrue(false, “My custom failure message”);
Refactoring the CalculatorTest.php
file
- Open the
CalculatorTest.php
file and edit the previous version:
We’ve changed several items in our code:
- We have imported the
App\Calculator
By doing this we won’t need to write new App\Calculator
instead, we will write new Calculator
- We have a private property in our class called
$calculator
- We have created a method called
setUp
This method is executed before each test method.
Thanks for reading this piece. I hope it could help you understand unit testing in PHP.