Pexels Cottonbro 6804581

走進 PHPUnit 的世界:從 0 到 1 的測試入門

為什麼要學 PHPUnit?

在上一篇文章裡,我們聊到了「還沒開始單元測試的你一定很忙」,同時也鼓勵大家「一個人就能開始測試」。那麼接下來就要進入更實際的操作層面,帶你走進 PHP 最常見的測試框架 —— PHPUnit

很多人對 PHPUnit 的印象是「很複雜、很多設定檔、好多斷言(assert)方法」。但事實上,只要掌握幾個核心概念,就能在短時間內寫出第一支測試。就像所有新事物一樣,最難的往往是那「踏出第一步」。我們就一起從 0 開始,帶你做到 1!


為什麼選擇 PHPUnit?

  1. 社群資源豐富 PHPUnit 在 PHP 生態系已耕耘多年,有大量的教學資源與社群討論,一遇到問題很容易查詢到解法。
  2. 與框架或純 PHP 都相容 無論是 Laravel 等主流框架,或是純 PHP 專案都可以整合 PHPUnit,相當彈性。
  3. Composer 管理輕鬆安裝 PHPUnit 的安裝與升級都能透過 Composer 完成,對於現代 PHP 專案來說相當方便。

雖然 PHPUnit 很主流,但也不是唯一選擇。市面上還有像 Pest、Codeception、PHPSpec 等。不同框架、不同專案需求不一,最終還是看你的開發生態做選擇。這裡先以 PHPUnit 作為「從 0 到 1」的首選示範。


安裝與初始化

建立或確認你的專案環境

  • 先準備好一個 PHP 專案目錄(舉例:my-php-project),並確保你的電腦已經安裝 PHP 與 Composer。

透過 Composer 安裝 PHPUnit

在專案目錄下,執行下列指令:

Bash
composer require --dev phpunit/phpunit
  • -dev 參數代表這是開發時期使用的套件,不會在正式環境上線時被引入(或會以不同方式處理)。

檢查安裝成功

安裝完成後,你可以在終端機執行:

Bash
vendor/bin/phpunit --version

若能看到 PHPUnit 的版本號,表示安裝成功。


寫下你的第一個測試

建立測試資料夾結構

通常我們會在專案裡建立一個 tests 資料夾,來放所有測試程式碼。

  • 結構示例:
Bash
my-php-project/
├── src/
|    └── MyCalculator.php
├── tests/
|    └── MyCalculatorTest.php
└── composer.json

寫個簡單的功能:MyCalculator (示範)

假設我們有一個簡單的類別 MyCalculator,負責做加法、減法。

PHP
<?php
// 檔案路徑: src/MyCalculator.php
namespace App;

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

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

建立測試檔 MyCalculatorTest

PHP
<?php
// 檔案路徑: tests/MyCalculatorTest.php
use PHPUnit\\Framework\\TestCase;
use App\\MyCalculator;

class MyCalculatorTest extends TestCase
{
    public function testAdd()
    {
        // Arrange
        $calc = new MyCalculator();

        // Act
        $result = $calc->add(2, 3);

        // Assert
        $this->assertEquals(5, $result, '2 + 3 應該等於 5');
    }

    public function testSub()
    {
        $calc = new MyCalculator();
        $result = $calc->sub(5, 2);
        $this->assertEquals(3, $result, '5 - 2 應該等於 3');
    }
}

這支測試分為三個常見步驟:

  • Arrange(初始化/準備):建立或準備要測試的物件、參數。
  • Act(執行):呼叫我們要測試的方法。
  • Assert(斷言):檢查結果是否符合預期。

執行測試

回到終端機,在專案根目錄執行:

Bash
vendor/bin/phpunit tests

(或僅輸入 vendor/bin/phpunit,它會自動尋找 tests 資料夾。)

如果一切順利,你會在終端機看到類似:

Bash
PHPUnit x.y.z by Sebastian Bergmann and contributors.

..                                                              2 / 2 (100%)

OK (2 tests, 2 assertions)

這代表你的兩個測試(testAddtestSub)都通過了!

此時,你已「舉出一個實例」來證明自己成功寫了測試,也驗證了程式運作正常。這份信心很重要,因為很多人都卡在「不知道怎麼開始」。


反例示範:測試失敗時該怎麼辦?

為了讓你感受「測試失敗會長什麼樣子」,我們故意改一下 MyCalculator::sub()

PHP
public function sub($a, $b)
{
    return $a + $b; // 故意改錯
}

再執行一次測試,你可能會看到:

Bash
There was 1 failure:

1) MyCalculatorTest::testSub
Failed asserting that 7 matches expected 3.

這行訊息就很直接地告訴你,預期應該得到 3,實際卻是 7,於是測試失敗。如此一來,你能在開發階段就抓到錯誤,而不必等到功能上線或被 QA 測出來。


更多 PHPUnit 常見斷言

  1. assertTrue($condition) / assertFalse($condition) 檢查布林值。
  2. assertEquals($expected, $actual) 檢查預期值與實際值是否相等。
  3. assertCount($expectedCount, $array) 檢查陣列的長度是否符合預期。
  4. assertNull($variable) 檢查變數是否為 null。
  5. assertInstanceOf($expectedClass, $object) 檢查物件是否屬於預期的類別。

這只是 PHPUnit 常見斷言的冰山一角,它的功能非常豐富。未來若有更複雜的測試場景(例:例外拋出、時間相關測試、mock 物件等),你都可以在官方文件或社群中找到相應做法。


測試與程式設計的良性循環

在寫測試的過程中,往往能促使我們寫出更結構化的程式碼,因為「要測試,就得讓程式碼更容易被呼叫、被拆分」。這是一個良性循環:

  • 寫測試 → 想要「好測」,於是去「重構程式、拆成小模組」。
  • 程式結構更好 → 寫更多測試也更輕鬆。
  • 好測試 → 開發速度與穩定度都提升。

就算是小專案,也能透過 PHPUnit 改善品質,讓你對自己的程式更有信心。


結論與後續

恭喜你!如果你跟著這篇示範,成功跑出你的第一個「單元測試」,那就已經從 0 來到 1 了。

  • 只要你的測試檔能正常跑通,就足以證明「你已經會寫單元測試」。
  • 要做到大範圍測試覆蓋、處理更複雜的業務邏輯,還需要不斷學習與演進。這篇文章只是帶你踏出第一步。

在下一篇,我們將帶領大家進一步進入 Laravel Test 實戰。利用 Laravel 已經內建的強大測試工具和輔助方法,讓你在框架環境下更輕鬆地測試 Controller、路由、資料庫操作等。敬請期待!

本文重點回顧

  1. 安裝 PHPUnit:Composer 快速安裝。
  2. 建立測試檔案與範例:一個簡單的 MyCalculator 測試,引導你做「Arrange、Act、Assert」。
  3. 執行測試、查看結果:了解測試通過(綠燈)與失敗(紅燈)時的訊息。
  4. 常用斷言assertEquals() 等基礎用法。
  5. 思考測試與程式結構:撰寫測試是改善程式架構的好時機。

下一篇(Laravel Test 實戰:與框架結合的測試技巧)見!一起繼續把測試應用到更真實的專案情境。