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 theadd()
method of theCalculator
class.testSubtraction()
– Tests thesubtract()
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.