Writing unit tests in PHP using PHPUnit

Arman Ahmadi
Webtips
Published in
7 min readDec 7, 2019
Unit Testing
Unit Testing

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:

  1. In procedural programming, a unit is often an individual function or procedure.
  2. 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.

PHPUnit framework
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
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.

phpunit.xml file
phpunit.xml

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 executed
  • name=”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

  1. Open the Composer.json file and add the autoload part like this:
composer.json autoload
composer.json autoload

The APP\\ says that the namespace we’re using will be App and appwill use the appdirectory 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 example MyFirstTest
  • 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 testlike ‘testMyFunction’
  1. Create two folders and name them app and some rules musttests
root directory
root directory

Now your root directory must be like the picture above.

2. Now run this command in your command line: ./vendor/bin/phpunit

./vendor/bin/phpunit no tests executed
no tests executed

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

Warning! no tests found in class “CalculatorTest”
Warning! no tests found in class “CalculatorTest”

As you can see we have got a warning and that’s because we have no method in the CalculatorTestclass.

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 calculatorobject 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 appfolder 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 operandsproperty 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

Test Passed!

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

  1. Open the CalculatorTest.php file and edit the previous version:
CalculatorTest.php file refactoring

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.

--

--