This website uses cookies

Our website, platform and/or any sub domains use cookies to understand how you use our services, and to improve both your experience and our marketing relevance.

CloudwaysCDN — a powerful solution that offers superior performance and satisfied global audience for your business. Read More

PHP Unit Testing Using PHPUnit Framework

Updated on  16th August

7 Min Read
Reading Time: 7 minutes

This article is the first one in the series of articles that focus on `Unit Testing`, a well known test methodology. I will use `PHPUnit` as the main test tool for PHP Unit Testing. Once you get hold of the basics, getting started with PHPUnit is not that difficult.

Even a small software development project usually takes hours of hard work. During the course of development, a number of major and minor bugs and problems creep in the structure and code of the application. Developers usually try to work out the bugs during the process of development.

The problem is that there is no surefire way of ensuring that all the bugs have been worked out of the final code. Another important aspect is the possibility of the introduction of further bugs when existing bugs are fixed. To address these problems, testing and QA are integral components of the software development process.

Testing and QA are integral components of software development process.

Careful software development ensures that some test and QA methodology is built in the development process from the very beginning. The result of such a development process is a robust code that is easy to maintain and extend further.

You might also like: PHP Continuous Integration With Travis CI

What is Unit Testing?

The word `Unit` refers to a block of code, method or an individual or independent class. Unit testing is a software testing process in which code blocks are checked to see whether the produced result matches the expectations.  The units are tested by writing a unique test case. The unit test is generally automatic but could be implemented manually. I have designed a short algorithm to define it visually how unit test work.

php unit testing

Why do Unit Testing?

Test Driven Development is a practice in which you write a test first and code later to pass the test. This approach makes sure that the number of bugs must be solved while development. The developer tightly writes the test cases first and then the code, as this practice enables him to quickly find out the potential bugs.

  • Testing can be automated for speed.
  • Higher probability of bug free code
  • Easy to understand inherited code
  • Refactor code to the point of testability and understandability
  • Figure out what went wrong quickly with test cases
  • New features can be coded easily
  • It also minimizes the cost of change in software.

PHPUnit Supported Version

Right now, PHPUnit has multiple supported versions and got some massive updates due to the latest PHP versions released. So it is duly compatible with the current and upcoming versions of the PHP. The compatibility table is shown below.

Major Version PHP Compatibility Initial Release Support
PHPUnit 8 PHP 7.2, PHP 7.3, PHP 7.4 February 1, 2019 Support ends on February 5, 2021
PHPUnit 7 PHP 7.1, PHP 7.2, PHP 7.3 February 2, 2018 Support ends on February 7, 2020
PHPUnit 6 PHP 7.0, PHP 7.1, PHP 7.2 February 3, 2017 Support ends on February 1, 2019
PHPUnit 5 PHP 5.6, PHP 7.0, PHP 7.1 October 2, 2015 Support ended on February 2, 2018

Introducing PHPUnit 7

PHPUnit 7 is released on 2nd Feb 2018 come with interesting features, changes and removes exciting features.

Note: PHPUnit 7 requires PHP 7.1 or newer version

PHPUnit Solves Previous Compatibility Issues

The new version of the library solves the a number of compatibility issues faced in the previous versions of PHPUnit. For a detailed discussion on the topic, please check out the official documentation. I also suggest looking into the changelog of the library.

How to Install PHPUnit?

To explain PHP unit testing, I will use PHPUnit library, developed by `Sebastian Burgmen`.

Before using the library, you need to set up a proper environment. If you are doing unit testing in a local environment, you must install XAMPP, Composer, Enable Xdebug, and finally install PHPUnit. However, thanks to Cloudways PHP Hosting, you do not need to install anything except PHPUnit. Xdebug is easily enabled at a single click in the `Advance` tab in Server Management.

Related: How To Host PHP On DigitalOcean

Login to SSH terminal by using Master Credentials and go to the application folder by using the command

$ cd applications/qmsfumgabd/public_html/

To install PHPUnit from `Composer`, run the following command in SSH terminal.

public_html$ composer require --dev phpunit/phpunit ^7

For installing from composer.json, add the following lines of code.

{
 "require-dev": {
 "phpunit/phpunit": "^7"
 },
 "autoload": {
 "psr-0": {
 "UnitTestFiles": ""
 }
 }
}

You can also install PHPUnit manually by downloading the latest version of PHPUnit from the official Website.

How to Check PHP Version?

If you need to check your PHP Version so type following command on SSH Terminal

public_html$ php -v

Directory Structure

Before starting the test process using PHPUnit, a proper directory structure for the files to be tested is required. At present, the directory structure will looks like this.

|--vendor
|--composer.json
|--composer.lock
|--index.php

I will create a new folder for the files to be tested. Create a folder `UnitTestFiles`. In this folder, create a subfolder  `Test`. Create a new file `phpunit.xml` in this subfolder and add the following code to it.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php" colors = "true" verbase="true" stopOnFailute="false">

<testsuites>
<testsuite name="Application Test Suite">
<directory>/UnitTestFiles/Test/</directory>
</testsuite>
</testsuites>
</phpunit>

The `colors=”true”` will show the results in highlighted colors and `<directory>./UnitTestFiles/Test/</directory>` will ask PHPUnit for the location of the files to be tested.

Now the directory structure will look like:

|--vendor
|--UnitTestFiles/Test
|--phpunit.xml
|--composer.json
|--composer.lock
|--index.php

All the project files will be located in the root, while the files to be tested will be located in the  Test folder

You might also like: Introduction To Laravel Dusk: Testing Todo App

Basic Conventions to Write Unit Test Case

Following are some basic conventions and steps for writing tests with PHPUnit:

  1. Test File names should have a suffix Test. For example, if First.php needs to be tested,the name of the test file name will be FirstTest.php
  2. Similarly, If the class name is `MyFirstClass` than the test class name will be `MyFirstClassTest`.
  3. Add test as the prefix for method names. For example,if the method name is `getuser()`, then in test class, it will become `testgetuser()`. You can also use @test annotation in document block to declare it as a testing method.
  4. All testing methods are `public`
  5. MyFirstClassTest should be inherited from `PHPUnit\Framework\TestCase`

These are the major ground rules for the testing framework. The essential configurations and settings are all setup. It is now time to write the first test case.

Writing The First Unit Test Case in PHP

I will now start with a very simple test case.

Create a file FirstTest.php in UnitTestFiles/Test. Add the following code to it.

?php
namespace UnitTestFiles\Test;
use PHPUnit\Framework\TestCase;


class FirstTest extends TestCase
{
public function testTrueAssetsToTrue()
{
$condition = true;
$this->assertTrue($condition);
}
}
?>

This is very basic test.  In the first line, I mentioned the namesapace where the test files are located. In the second line, I initialized the PHPUnit framework. FirstTest is the test class that extends Testcase. I have declared a method `testTrueCheck()` with prefix test. In the method, I simply declares a variable `$condition = true`; I will next validate (true or false) this variable with `assertTrue`. Save the file and run it through the SSH terminal by using the following command

Here is the result of our first unit test. To do another test, pass false to the variable `$condition`. The present result `$condition = true` is changed to  `$condition = false;` Run the test command in SSH terminal.

This red line indicates the failure of the test since `assertTrue` reports an error and identified $condition as false.

Let’s look at another example in which a developer has created a code to take input an email address and validate it for the possible use case may be regex or for other email validation rules.

<?php

declare(strict_types=1);

final class Email

{

   private $email;

   private function __construct(string $email)

   {

       $this->ensureIsValidEmail($email);

       $this->email = $email;

   }

   public static function fromString(string $email): self

   {
       return new self($email);
   }

   public function __toString(): string

   {

       return $this->email;

   }

   private function ensureIsValidEmail(string $email): void

   {

       if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {

           throw new InvalidArgumentException(

               sprintf(

                   '"%s" is not a valid email address',

                   $email

               )

           );

       }

   }

}

I’ve created a class called Email which saves the email value in private variable and pass it to the constructor. The constructor has ensureIsValidEmail() method which further checks the email using FILTER_VALIDATE_EMAIL and throws an exception if not valid. Now in the UnitTestFiles/Test folder, create a new file called EmailTest.php and add the following test code:

<?php

declare(strict_types=1);

namespace UnitTestFiles\Test;

use PHPUnit\Framework\TestCase;



final class EmailTest extends TestCase

{

   public function testCanBeCreatedFromValidEmailAddress(): void

   {

       $this->assertInstanceOf(

           Email::class,

           Email::fromString('user@example.com')

       );

   }

   public function testCannotBeCreatedFromInvalidEmailAddress(): void

   {

       $this->expectException(InvalidArgumentException::class);



       Email::fromString('invalid');

   }

   public function testCanBeUsedAsString(): void

   {

       $this->assertEquals(

           'user@example.com',

           Email::fromString('user@example.com')

       );

   }

}

Here I’ve used assertInstanceOf() method which reports an error identified by $message if $actual is not an instance of $expected. So I’ve passed two arguments, the actual email class and the expected email address.The second test will take the input value and throw an invalid exception if the email value is not validated. The third test takes input value and treats it as an string.

Let’s run the test on composer by running the following command:

./vendor/bin/phpunit --bootstrap vendor/autoload.php Tests/EmailTest

Conclusion

This article explains a basic setup that help you in getting started with PHPUnit for PHP unit testing. I would like to  mention several changes in the latest version of PHPUnit. In the previous versions, the class extend with `PHPUnit_Framework_TestCase`. In the latest version, it extends with `TestCase` only. In the second article of this series, I will explain Assertions, data providers and other features in some details. If you have a question or would like to contribute to the discussion, please leave a comment.

Share your opinion in the comment section. COMMENT NOW

Shahroze Nawaz

Shahroze is a PHP Community Manager at Cloudways - A Managed PHP Hosting Platform. He’s always in search of new frameworks and methods to implement them. Besides his coding life, he loves movies and playing soccer with friends. You can email him at shahroze.nawaz@cloudways.com

Create PHP websites without the worry of server management.

Deploy your PHP app on optimized PHP hosting servers.

Get Our Newsletter
Be the first to get the latest updates and tutorials.

THERE’S MORE TO READ.