Page Content

Tutorials

PHPUnit : Writing And Running Unit Tests In PHP

One way to confirm that your code performs as intended is through unit testing. Dividing your code into the smallest logical parts is the foundation of unit testing. A unit in object-oriented PHP is usually a class method. A PHPunit in procedural PHP is a function. After that, each unit is tested separately to make sure it operates as planned.

It is generally accepted that any well-developed project must have a strong set of tests. You can gradually refactor your code after you have enough automated tests in place. You test code after relocating or altering it, and if it fails, you can easily identify the issue because you know it’s in the section of the program you just altered. Testing is the first step in software quality control, and unit testing, which tests each function point as written, contributes to process quality.

For automated PHP unit testing, PHPUnit is a popular open-source testing framework. PHPUnit, a common unit testing tool in the Java community, serves as its foundation. A regression testing framework called PHPUnit is utilised by developers who use PHP to create unit tests. It is among the most well-known PHP unit testing frameworks, along with SimpleTest. It has many functions and is a very strong tool.

Getting Started with PHPUnit

Using a package manager like Composer is frequently a smart approach to get started with PHPUnit. Using a package manager to install and maintain PHPUnit is regarded as best practice. In order to retrieve the code from the command line, you may also download it from the official website as a single phar file and put it in the root of your project.

Writing Unit Tests

Classes are used to write tests. PHPUnit\Framework\TestCase (or PHPUnit_Framework_TestCase in previous versions) is extended by these test classes. For PHPUnit to recognise that a file contains tests, the file and class names must finish in Test. Test class names are usually similar to the class being tested with a “Test” suffix.
The code being tested is included in the following basic test class structure:

<?php
// tests/YourClassTest.php
// Include the code you want to test
require_once __DIR__ . '/../src/YourClass.php'; // Example path
use PHPUnit\Framework\TestCase; // Or use PHPUnit_Framework_TestCase for older versions
class YourClassTest extends TestCase {
    // Test methods go here
    public function testSomethingBasic() {
        //  assertions 
    }
}

Individual tests are represented by methods within these test classes. The term “test” usually appears at the beginning of test methods by convention. PHPUnit runs methods that begin with test inside the test class. PHPUnit will not run a method and will display a warning if the method name does not begin with test. Adding the @test annotation to the method’s DocBlock allows you to use any function name.

Long test method names that fully describe the function of the test are preferred. This helps you stay focused and improves the readability of the test and its output should things go wrong. In this way, a test must tell a tale.

Assertions form the core of any set of tests. A PHPUnit method that contrasts a known value with a value generated by the code you want to test is called an assertion. The test will be marked as failed and an error message will be displayed if an assertion is false. The list assertEquals(), assertTrue(), assertFalse(), assertSame(), assertContains(), and assertType() as common test assertion methods.

Additionally, examples make use of the assertEmpty() technique. In the event that an assertion fails, a third optional parameter is frequently accepted for a text message to show. assertEquals() determines whether the first and second arguments are equal. assertSame() determines whether two values are identical.

Let’s see an example that tests a basic Book class.

<?php
// src/Book.php
class Book {
    public $title;
    public function __construct($title) {
        $this->title = $title;
    }
    public function getBook() {
        return $this->title;
    }
}
// tests/BookTest.php
require_once __DIR__ . '/../src/Book.php'; // Include the class to be tested
use PHPUnit\Framework\TestCase; // Or use PHPUnit_Framework_TestCase for older versions
class BookTest extends TestCase {
    public function testGetBookMethodReturnsCorrectTitle() { // Descriptive name
        $expected = 'PHP 7'; // The expected value
        $book = new Book('PHP 7'); // Instantiate the class
        $actual = $book->getBook(); // Get the actual value from the code under test
        $this->assertEquals($expected, $actual, 'Book title should match expected.'); // Assert equality, include optional message
    }
}

This test shows how to create a Book object, call its getBook function, and use assertEquals() to make sure that the $expected string and the method’s return value ($actual) match.

Setting Up and Tearing Down Tests

The setUp() and tearDown() functions are provided by PHPUnit. Every time a test of that class is run, the setUp() function if it exists is called before the test method. This is helpful for initialising the object that will be used, for example, and for creating a common test scenario for several tests in the class. You can store the context by using class properties because the instance of the class that calls the test and setUp methods is the same. Each test method is followed by the tearDown() method, if it exists.

Here’s an example of setUp() in action:

<?php
// tests/BasicTest.php
require_once __DIR__ . '/../src/Basic.php'; // Include the class to be tested (example)
use PHPUnit\Framework\TestCase; // Or use PHPUnit_Framework_TestCase for older versions
class BasicTest extends TestCase {
    private $customer; // Property to hold the object instance
    // setUp method runs before each test
    public function setUp(): void { // Use void return type hint in modern PHPUnit
        // Initialize the object or common test scenario
        $this->customer = new Basic(1, 'han', 'solo', 'han@solo.com'); // 
    }
    // tearDown method runs after each test (optional, but good practice for cleanup)
    protected function tearDown(): void { // Use protected visibility and void return type hint
        // Clean up 
        unset($this->customer);
    }
    public function testAmountToBorrow() {
        // Use the initialized object $this->customer
        $this->assertSame( // 
            3,
            $this->customer->getAmountToBorrow(), // 
            'Basic customer should borrow up to 3 books.' // Optional message
        );
    }
    // Other test methods would also use $this->customer, initialized by setUp()
}

In this example, an instance of the Basic class is created using setUp() and assigned to the class property $customer. $this->customer can then be used directly by test methods such as testAmountToBorrow. Here, the instance is cleaned up using tearDown().

Running Tests

The phpunit command can be used to execute unit tests from the command line. By giving the path to the file, you can run tests for a particular file. For instance, phpunit tests/BookTest.php or php phpunit.phar tests/BookTest.php if you’re using a phar file. You may frequently just run phpunit from the directory containing the phpunit.xml (or phpunit.xml.dist) configuration file in your project root, and it will find and execute your tests according to the configuration.


The outcomes will be reported using PHPUnit. All tests are in an OK status if everything is in order. The state will be “Fail” if a test is unsuccessful. Syntax problems are typically indicated by an error state. When a test is unsuccessful, the output may display both the actual result (often represented by a + sign) and the expected value (typically represented by a – sign).

The number of lines in the backend code that were tested can be seen by running with extra parameters like –coverage. Code coverage is the percentage of tested code or the quantity of code that is executed by your tests. This helps you find the areas of your application that haven’t been tested.

Related Concepts

Test-Driven Development (TDD) is also mentioned in the albeit it is not discussed in great detail in a basic introduction. developing unit tests before developing the actual code is part of the TDD technique. The plan is to write a test, make sure it fails, write the bare minimum of code to pass, and then run the tests again in a progressive manner.

Additionally, PHPUnit has capabilities like Data Providers that let you run the same test function on different data. Using test duplicates, such as mocks, to isolate the code under test is another sophisticated method that is considered to delve deeper into the world of unit testing.

Because it allows for more reliable code and trust during refactoring and development, unit testing is essential to contemporary software development processes.

Index