為什麼要學 PHPUnit?
在上一篇文章裡,我們聊到了「還沒開始單元測試的你一定很忙」,同時也鼓勵大家「一個人就能開始測試」。那麼接下來就要進入更實際的操作層面,帶你走進 PHP 最常見的測試框架 —— PHPUnit。
很多人對 PHPUnit 的印象是「很複雜、很多設定檔、好多斷言(assert)方法」。但事實上,只要掌握幾個核心概念,就能在短時間內寫出第一支測試。就像所有新事物一樣,最難的往往是那「踏出第一步」。我們就一起從 0 開始,帶你做到 1!
為什麼選擇 PHPUnit?
- 社群資源豐富 PHPUnit 在 PHP 生態系已耕耘多年,有大量的教學資源與社群討論,一遇到問題很容易查詢到解法。
- 與框架或純 PHP 都相容 無論是 Laravel 等主流框架,或是純 PHP 專案都可以整合 PHPUnit,相當彈性。
- Composer 管理輕鬆安裝 PHPUnit 的安裝與升級都能透過 Composer 完成,對於現代 PHP 專案來說相當方便。
雖然 PHPUnit 很主流,但也不是唯一選擇。市面上還有像 Pest、Codeception、PHPSpec 等。不同框架、不同專案需求不一,最終還是看你的開發生態做選擇。這裡先以 PHPUnit 作為「從 0 到 1」的首選示範。
安裝與初始化
建立或確認你的專案環境
- 先準備好一個 PHP 專案目錄(舉例:
my-php-project
),並確保你的電腦已經安裝 PHP 與 Composer。
透過 Composer 安裝 PHPUnit
在專案目錄下,執行下列指令:
composer require --dev phpunit/phpunit
-dev
參數代表這是開發時期使用的套件,不會在正式環境上線時被引入(或會以不同方式處理)。
檢查安裝成功
安裝完成後,你可以在終端機執行:
vendor/bin/phpunit --version
若能看到 PHPUnit 的版本號,表示安裝成功。
寫下你的第一個測試
建立測試資料夾結構
通常我們會在專案裡建立一個 tests
資料夾,來放所有測試程式碼。
- 結構示例:
my-php-project/
├── src/
| └── MyCalculator.php
├── tests/
| └── MyCalculatorTest.php
└── composer.json
寫個簡單的功能:MyCalculator
(示範)
假設我們有一個簡單的類別 MyCalculator
,負責做加法、減法。
<?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
// 檔案路徑: 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(斷言):檢查結果是否符合預期。
執行測試
回到終端機,在專案根目錄執行:
vendor/bin/phpunit tests
(或僅輸入 vendor/bin/phpunit
,它會自動尋找 tests
資料夾。)
如果一切順利,你會在終端機看到類似:
PHPUnit x.y.z by Sebastian Bergmann and contributors.
.. 2 / 2 (100%)
OK (2 tests, 2 assertions)
這代表你的兩個測試(testAdd
和 testSub
)都通過了!
此時,你已「舉出一個實例」來證明自己成功寫了測試,也驗證了程式運作正常。這份信心很重要,因為很多人都卡在「不知道怎麼開始」。
反例示範:測試失敗時該怎麼辦?
為了讓你感受「測試失敗會長什麼樣子」,我們故意改一下 MyCalculator::sub()
:
public function sub($a, $b)
{
return $a + $b; // 故意改錯
}
再執行一次測試,你可能會看到:
There was 1 failure:
1) MyCalculatorTest::testSub
Failed asserting that 7 matches expected 3.
這行訊息就很直接地告訴你,預期應該得到 3,實際卻是 7,於是測試失敗。如此一來,你能在開發階段就抓到錯誤,而不必等到功能上線或被 QA 測出來。
更多 PHPUnit 常見斷言
assertTrue($condition)
/assertFalse($condition)
檢查布林值。assertEquals($expected, $actual)
檢查預期值與實際值是否相等。assertCount($expectedCount, $array)
檢查陣列的長度是否符合預期。assertNull($variable)
檢查變數是否為 null。assertInstanceOf($expectedClass, $object)
檢查物件是否屬於預期的類別。
這只是 PHPUnit 常見斷言的冰山一角,它的功能非常豐富。未來若有更複雜的測試場景(例:例外拋出、時間相關測試、mock 物件等),你都可以在官方文件或社群中找到相應做法。
測試與程式設計的良性循環
在寫測試的過程中,往往能促使我們寫出更結構化的程式碼,因為「要測試,就得讓程式碼更容易被呼叫、被拆分」。這是一個良性循環:
- 寫測試 → 想要「好測」,於是去「重構程式、拆成小模組」。
- 程式結構更好 → 寫更多測試也更輕鬆。
- 好測試 → 開發速度與穩定度都提升。
就算是小專案,也能透過 PHPUnit 改善品質,讓你對自己的程式更有信心。
結論與後續
恭喜你!如果你跟著這篇示範,成功跑出你的第一個「單元測試」,那就已經從 0 來到 1 了。
- 只要你的測試檔能正常跑通,就足以證明「你已經會寫單元測試」。
- 要做到大範圍測試覆蓋、處理更複雜的業務邏輯,還需要不斷學習與演進。這篇文章只是帶你踏出第一步。
在下一篇,我們將帶領大家進一步進入 Laravel Test 實戰。利用 Laravel 已經內建的強大測試工具和輔助方法,讓你在框架環境下更輕鬆地測試 Controller、路由、資料庫操作等。敬請期待!
本文重點回顧
- 安裝 PHPUnit:Composer 快速安裝。
- 建立測試檔案與範例:一個簡單的
MyCalculator
測試,引導你做「Arrange、Act、Assert」。 - 執行測試、查看結果:了解測試通過(綠燈)與失敗(紅燈)時的訊息。
- 常用斷言:
assertEquals()
等基礎用法。 - 思考測試與程式結構:撰寫測試是改善程式架構的好時機。
下一篇(Laravel Test 實戰:與框架結合的測試技巧)見!一起繼續把測試應用到更真實的專案情境。