在上一篇文章裡,我們聊到了「還沒開始單元測試的你一定很忙」,同時也鼓勵大家「一個人就能開始測試」。那麼接下來就要進入更實際的操作層面,帶你走進 PHP 最常見的測試框架 —— PHPUnit。
很多人對 PHPUnit 的印象是「很複雜、很多設定檔、好多斷言(assert)方法」。但事實上,只要掌握幾個核心概念,就能在短時間內寫出第一支測試。就像所有新事物一樣,最難的往往是那「踏出第一步」。我們就一起從 0 開始,帶你做到 1!
雖然 PHPUnit 很主流,但也不是唯一選擇。市面上還有像 Pest、Codeception、PHPSpec 等。不同框架、不同專案需求不一,最終還是看你的開發生態做選擇。這裡先以 PHPUnit 作為「從 0 到 1」的首選示範。
建立或確認你的專案環境
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');
}
}
這支測試分為三個常見步驟:
執行測試
回到終端機,在專案根目錄執行:
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 測出來。
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、路由、資料庫操作等。敬請期待!
MyCalculator
測試,引導你做「Arrange、Act、Assert」。assertEquals()
等基礎用法。下一篇(Laravel Test 實戰:與框架結合的測試技巧)見!一起繼續把測試應用到更真實的專案情境。