Writing Your First Unit Test in PHP Using PHPUnit

Writing Your First Unit Test in PHP Using PHPUnit

Learn how to write your first unit test in PHP using PHPUnit. Set up your test environment, create test cases, and run automated tests for reliable PHP applications.

Introduction

Unit testing is a critical part of software development that helps ensure code reliability, maintainability, and bug prevention. PHPUnit is the most widely used testing framework for PHP applications, allowing developers to write and execute automated tests efficiently.

With PHPUnit, you can:

  • Verify that functions and methods behave correctly
  • Prevent regression issues when making code changes
  • Automate testing to improve code quality
  • Integrate testing into CI/CD workflows for faster development

This guide will cover:

  • Installing PHPUnit and setting up a test environment
  • Writing your first unit test step by step
  • Running and analyzing test results

1. Installing PHPUnit

Before writing tests, you need to install PHPUnit. The recommended way is via Composer.

Install PHPUnit Globally

Run the following command to install PHPUnit globally:

composer global require phpunit/phpunit

After installation, verify the installation with:

phpunit --version

Install PHPUnit for a Specific Project

To install PHPUnit as a dev dependency in a project:

composer require --dev phpunit/phpunit

After installation, check the installed version:

vendor/bin/phpunit --version

2. Setting Up PHPUnit in a PHP Project

Create a tests Directory

Inside your project, create a tests directory:

mkdir tests

Generate a PHPUnit Configuration File (Optional but Recommended)

Create a phpunit.xml file in the project root to configure PHPUnit:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php">
    <testsuites>
        <testsuite name="Application Test Suite">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
</phpunit>

This configuration automatically loads dependencies and runs tests in the tests directory.

3. Writing Your First Unit Test

Step 1: Create a Simple PHP Class

Create a file named Calculator.php inside a src/ directory:

<?php

namespace App;

class Calculator
{
    public function add($a, $b)
    {
        return $a + $b;
    }

    public function subtract($a, $b)
    {
        return $a - $b;
    }
}

Step 2: Create a Test File

Create a test file in the tests directory named CalculatorTest.php:

mkdir -p tests/Unit
touch tests/Unit/CalculatorTest.php

Step 3: Write a PHPUnit Test

Edit CalculatorTest.php and write your first test:

<?php

use PHPUnit\Framework\TestCase;
use App\Calculator;

class CalculatorTest extends TestCase
{
    public function testAddition()
    {
        $calculator = new Calculator();
        $result = $calculator->add(2, 3);

        $this->assertEquals(5, $result);
    }

    public function testSubtraction()
    {
        $calculator = new Calculator();
        $result = $calculator->subtract(5, 2);

        $this->assertEquals(3, $result);
    }
}

Explanation:

  • use PHPUnit\Framework\TestCase; – Extends the TestCase class to enable PHPUnit testing.
  • $this->assertEquals(expected, actual); – Compares the expected result with the actual output.
  • testAddition() – Tests the add() method of the Calculator class.
  • testSubtraction() – Tests the subtract() method.

4. Running Your First Unit Test

Run the test using:

vendor/bin/phpunit tests

Expected Output:

PHPUnit 10.0.0 by Sebastian Bergmann and contributors.

..                                                              2 / 2 (100%)

Time: 00:00.012, Memory: 6.00 MB

OK (2 tests, 2 assertions)
  • The .. means both tests passed.
  • The assertions confirm that the functions return expected values.

5. Handling Failing Tests

Modify the Calculator.php class to introduce an error:

public function add($a, $b)
{
    return $a * $b; // Intentional bug
}

Run the tests again:

vendor/bin/phpunit tests

Expected Output:

PHPUnit 10.0.0 by Sebastian Bergmann and contributors.

F.                                                              2 / 2 (100%)

Time: 00:00.014, Memory: 6.00 MB

There was 1 failure:

1) CalculatorTest::testAddition
Failed asserting that 6 matches expected 5.

/tests/Unit/CalculatorTest.php:10
  • F. indicates one failed test and one passed test.
  • The error message helps debug the failing test case.

6. Improving Tests with More Assertions

PHPUnit provides multiple assertion methods to validate behavior:

$this->assertEquals(5, $result); // Check if values match
$this->assertNotEquals(4, $result); // Ensure values are different
$this->assertGreaterThan(4, $result); // Ensure result is greater than 4
$this->assertLessThan(6, $result); // Ensure result is less than 6
$this->assertIsInt($result); // Ensure result is an integer

Updating tests with multiple assertions improves test coverage and reliability.

7. Automating Tests with GitHub Actions (CI/CD Integration)

Create a GitHub Workflow File

Inside your project, create .github/workflows/phpunit.yml:

name: Run PHPUnit Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout Code
      uses: actions/checkout@v3

    - name: Setup PHP
      uses: shivammathur/setup-php@v2
      with:
        php-version: '8.1'
        tools: composer

    - name: Install Dependencies
      run: composer install --no-progress --no-suggest --prefer-dist

    - name: Run PHPUnit Tests
      run: vendor/bin/phpunit tests

Why Use CI/CD for Testing?

  • Runs tests automatically on every commit.
  • Prevents bugs from reaching production.
  • Ensures code quality across multiple contributors.

8. Best Practices for Writing Unit Tests in PHP

  • Follow the Arrange-Act-Assert pattern (AAA) in tests.
  • Use meaningful test names (e.g., testUserCanLogin()).
  • Avoid testing multiple functions in one test.
  • Use test doubles (mocks and stubs) for dependencies.
  • Run tests frequently to catch bugs early.

Conclusion

Writing unit tests in PHP using PHPUnit improves code quality, reliability, and maintainability.

This guide covered:

  • Installing and setting up PHPUnit
  • Writing and running your first unit test
  • Handling test failures and debugging
  • Integrating PHPUnit into CI/CD for automation

By incorporating unit tests into your development workflow, you can catch errors early and build robust PHP applications.

Leave a Reply