Skip to main content

Pest 為何成為 Laravel 的預設

自 Laravel 11 起,用 laravel new 建立專案時 Pest 就成為預設的測試框架。PHPUnit 長期以來是 PHP 標準測試工具,但 Pest 以 PHPUnit 為基礎,提供更簡潔易讀的測試寫法。
Pest 執行於 PHPUnit 之上,既有的 PHPUnit 測試可原樣執行,遷移可循序進行。
官方採用 Pest 的背後有一個目標:減少寫測試的摩擦。它省去「定義類別、寫方法」的儀式性步驟,讓開發者專注於「想測什麼」本身,測試的撰寫習慣就更容易養成。

與 PHPUnit 的主要差異

測試寫法

最直觀的差異就是寫法。
Pest 的 test() 函式接收 closure。因為不需定義類別或方法,測試的意圖從第一行就清楚。it() 用法相同。以英文書寫時可讀為 it('can login', ...) 這樣自然的句子。

expect() API

Pest 最大特色是用 expect() 的鏈式斷言。
expect($value)->toBe()->toBeNull()->toContain()->toHaveCount() 等以近似英文自然句的形式寫斷言。多個斷言可用方法鏈組合起來。

Setup 與 Teardown

PHPUnit 的 setUp() 對應 beforeEach()tearDown() 對應 afterEach()

Dataset — 表格式驅動測試

若要以多筆資料執行同一測試邏輯,可用 dataset
每筆資料集的 label(如 '沒有 email')會出現在測試名稱上,能一眼看出是哪個模式失敗。

arch() 測試 — 自動檢查架構

Pest 的 arch() 是驗證程式碼庫結構的測試。像「Controller 是否直接依賴 Model」「Model 是否繼承 Eloquent」這類架構規則能自動驗證。
arch() 測試以靜態分析原始碼執行,不會真的發 HTTP 請求或存取 DB,速度非常快。
Pest 也提供常用架構規則的預設集。
laravel() 預設集會依 Laravel 一般慣例驗證 Model 命名、Controller 繼承、Middleware 結構等。

Laravel 專案的實務範例

建立測試

於 Laravel 11 以後保持預設設定執行時,會產生 Pest 格式的測試檔。

直接使用 Laravel 的測試 helper

Pest 繼承自 Laravel 的 TestCase,因此 actingAs()assertDatabaseHas()、HTTP 測試 helper 等所有 Laravel 測試 helper 都可以直接使用。

Factory 與資料庫交易

RefreshDatabaseDatabaseTransactions trait 也能透過 uses() 輕鬆套用。寫在檔案開頭就會套用整份檔案。
tests/Pest.php 設定一次後,所有 Feature 測試就會自動啟用 RefreshDatabase,也可於個別測試檔覆寫。

與既有 PHPUnit 測試共存

Pest 與 PHPUnit 可以在同一專案共存。既有 PHPUnit 測試不必改寫,只要新測試用 Pest 格式書寫即可。
自 Laravel 11 起,php artisan test 若已安裝 Pest 會自動用 Pest 執行。

遷移步驟

  1. 首先於 tests/Pest.php 加上 uses() 設定
  2. 新加的測試以 Pest 格式書寫
  3. 既有 PHPUnit 測試邊確認邊逐步遷移
不必急著把所有測試重寫。Pest 的語法相較 PHPUnit 學習成本較低,向團隊推廣也相對順利。

總結

Pest 不是 PHPUnit 的替代品,而是包在 PHPUnit 上的上層。與 Laravel 整合深入,甚至在啟動套件產生時就作為預設選項。導入既有專案成本低,只要從新測試開始試就能享受其好處。 當測試量增加時,能更快發現 bug,重構的心理阻力也降低。Pest 就是為了減少「撰寫測試本身的摩擦」而生的工具。

Pest 官方文件

Dataset、覆蓋率、平行執行等 Pest 完整功能,請參考官方文件。
最後修改於 2026年8月2日