How to test PHP code using PHPUnit

PHPUnit automatically executable tests that verify your application’s behavior. Thus – you can ensure that your changes don’t break existing functionality. This post will show you how to test your PHP code using PHPUnit.

YouTube player
You can learn more about coding here. We discuss PHP, Bash, and more.

Setup PHPUnit

You can setup PHPUnit using the following terminal command after navigating to the project directory:

composer require --dev phpunit/phpunit ^9

As a result, the command will add the requirement of PHPUnit to your composer.json file. Composer will then install the dependencies. With that, you are all set and ready to go!

Note that:

  • PHPUnit should be set up on a per-project basis.
  • PHPUnit should only be used in a development environment.
  • Using PHPUnit on a web-server will result in unwanted behavior.
  • This post uses Composer for the installation of PHPUnit.

Test the PHP code with PHPUnit

PHPUnit allows the user to test multiple use cases in one go. For example, instead of writing code and using var_dump or print_r to confirm values, you can write a PHPUnit test by asserting the obtained result against the expected result. Don’t worry! We will discuss assertions in more detail.

Example code to test

Consider the following PHP class Password, which checks for the strength of a password.

The method get_strength() is used to evaluate the password’s strength—the method checks for two types of data: alphabetical and numeric. The password strength is determined by the number of data types it contains. The method returns a score of 1 for weak and 2 for strong. The validate() method checks if the password is greater than eight, and the score is greater than 0. If the validation fails, the InvalidPasswordException is thrown.

<?php
class Password {
    protected $password = "";
    function __construct($password = "")
    {
        $this->password = $password;
    }
    public function validate(){
        if(strlen($this->password) < 8){
            throw new InvalidPasswordException();
        }
        if($this->get_strength() == 0){
            throw new InvalidPasswordException();
        }
    }
    public function get_strength(){
        $strength = 0;
        if(preg_match('/[A-Za-z]/', $this->password)){
            // Letter found!
            $strength +=1;
        }
        if(preg_match('/[0-9]/', $this->password)){
            // Digit found!
            $strength += 1;
        }
        return $strength;
    }
}
class InvalidPasswordException extends Exception{
    public function errorMessage()
    {
       //error message
       $errorMsg = 'Invalid password. Make sure the password length is more than 8 and contains alphanumeric characters.';
       return $errorMsg;
    }
}

Here are some use-cases for the Password class:

  • One data-type password gives a score of 1
  • Two data-types password gives a score of 2
  • Symbols only password (score of 0) throws an exception upon validation
  • A password of length seven or less throws an exception upon validation

Testing the possible use cases for the Password class is by printing and comparing every use case. However, PHPUnit provides a more robust method for testing. Let us begin by making a file PasswordTest.php.

Example tests

PHPUnit has some conventions which the framework uses for testing:

  • Tests for class ClassName go by ClassNameTest, i.e. it begins with the class name and ends with Test.
  • The test classes inherit PHPUnit/Framework/TestCase. This allows the test classes to use PHPUnit methods like assertions.
  • Each test inside the class is a public function. The name of the function begins with test*.

These functions will use assertions to test the code. A failed assertion fails the test. One test may have several assertions, e.g. In Password class test case 1, you will need to assert each of the two data-types one by one to confirm that one data-type password gives the score 1. Hence one test will have multiple assertions.

The class PasswordTest tests each of the 4 test cases for Password class one by one. Each of the use cases is tested separately. Each function in the class tests for one of the use-cases. Another convention is that the name of the function (camel-cased words followed by the word test*) is also a short description of what the test does.

<?php
// Loading up TestCase
use PHPUnit\Framework\TestCase;

require "Password.php";

class PasswordTest extends TestCase{

    public function testOneDatatypePasswordGivesScoreOf1(){
        $pass = new Password("Foopassword");
        $strength = $pass->get_strength();

        // Asserting that strength is 1
        $this->assertEquals(1, $strength);

        $pass = new Password("123123123");
        $strength = $pass->get_strength();

        // Asserting that strength is 1
        $this->assertEquals(1, $strength);
    }
    public function testTwoDatatypePasswordGivesScoreOf2(){
        $pass = new Password("Foobar123");
        $strength = $pass->get_strength();

        // Asserting that strength is 1
        $this->assertEquals(2, $strength);
    }
    public function testScoreOf0ThrowsException()
    {
        // Declaring an Exception is expected in the below code
        $this->expectException(InvalidPasswordException::class);
        $pass = new Password("#!#!#!!#!#!");
        $pass->validate();
    }
    public function testPasswordLengthLessThan8ThrowsException()
    {
        // Declaring an Exception is expected in the below code
        $this->expectException(InvalidPasswordException::class);
        $pass = new Password("foo");
        $pass->validate();
    }
}

For testing, we use assert* methods. For exceptions, we can use expectExeption (Exception::class) to test whether the code correctly throws an exception.

Testing your PHP code

Testing is quite simple with PHPUnit. You need to run the following command from your project directory:

./vendor/bin/PHPUnit PasswordTest.php

If all tests succeed, the following output will be given:

Another way is to test using the function names as short descriptions for each test:

./vendor/bin/PHPUnit --testdox PasswordTest.php

PHPUnit can also be used to test all test files in a directory using the following command:

./vendor/bin/PHPUnit

Or:

./vendor/bin/PHPUnit --testdox

The output will be very similar to the above.

Wrapping up

PHPUnit is a robust PHP testing framework. PHPUnit requires a *Test.php file containing a *Test class. The class must extend PHPUnit\Framework\TestCase class. You can then perform your tests.

You may also be interested in

Source:

About Anto Online

Anto, a seasoned technologist with over two decades of experience, has traversed the tech landscape from Desktop Support Engineer to enterprise application consultant, specializing in AWS serverless technologies. He guides clients in leveraging serverless solutions while passionately exploring cutting-edge cloud concepts beyond his daily work. Anto's dedication to continuous learning, experimentation, and collaboration makes him a true inspiration, igniting others' interest in the transformative power of cloud computing.

View all posts by Anto Online

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.