「後台是用 Filament 這種管理面板套件開發的,測試也要照一般 HTTP 頁面那樣打請求、看回應內容嗎?」
答案是不行——至少不是最有效的方式。Filament 這類後台管理套件,介面背後是用 Livewire 元件組成的,使用者在畫面上點的每一個按鈕、填的每一個表單,最終都是在跟一個 Livewire 元件互動,不是傳統的表單送出、整頁重新整理。這代表測試後台功能時,要測的重點不是「這個 HTTP 請求回傳了什麼畫面」,而是「這個操作有沒有真的觸發該發生的動作」。
先說清楚:這篇只講測試手法本身,不會深入教 Filament 這套後台框架怎麼開發,重點放在「怎麼驗證一個後台操作真的有效」這件事。
一般網頁的一次互動,通常對應到「送出一個 HTTP 請求,伺服器處理完回傳一個新頁面(或一段資料)」。但 Livewire 元件的互動模型不一樣:畫面上的一個按鈕,對應到的是「呼叫這個元件身上的某個方法」,元件內部的狀態變化,再透過背景的請求同步回畫面。
這代表如果你想用傳統的 post('/admin/news') 這種方式去測試「新增一筆新聞」這個後台操作,會遇到困難——因為使用者實際操作時,根本不是直接送出一個表單到某個固定路由,而是在跟一個活生生的元件互動,元件內部可能還有多個步驟、多個狀態切換。
Laravel 生態裡測 Livewire 元件的標準做法,是直接把元件當成一個可以呼叫方法、觸發事件的物件來操作,跳過「模擬使用者在瀏覽器裡點擊」這層,直接對元件本身下指令、檢查元件執行後的狀態。
這個系統的後台有一個新聞列表頁,上面有一個「匯出」功能,讓管理員可以把目前列表的資料匯出成 CSV 檔案。測試這個功能的重點,不是「畫面上有沒有出現匯出按鈕」,而是**「點了匯出之後,有沒有真的產生一個內容正確的 CSV 檔案」**。
test('can export news list', function () {
asAdmin();
Storage::fake('local');
News::factory()->count(3)->create();
livewire(ListNews::class)
->mountTableAction('export')
->callMountedTableAction();
Storage::disk('local')->assertExists('filament_exports/1/0000000000000001.csv');
});
這支測試做了幾件事:先用測試輔助函式登入一個有權限的管理員身份,接著假造一個本機硬碟(不會真的寫進正式的檔案系統),準備好三筆新聞資料,然後直接對「新聞列表」這個 Livewire 元件下指令——掛載匯出這個表格動作、觸發它執行。最後驗證的不是任何畫面上的文字,而是假硬碟裡真的出現了一個特定路徑的 CSV 檔案。
這種驗證方式回答的問題是:「這個匯出按鈕背後串接的邏輯,真的有把資料寫成一個檔案」,而不是「畫面上顯示了『匯出成功』這幾個字」。後者只驗證了介面文字,前者驗證了功能本身確實運作。
test('admin can create news', function () {
asAdmin();
post('/admin/news', [
'title' => '測試新聞',
'content' => '內容',
])->assertRedirect();
});
這種寫法假設後台表單送出跟傳統網頁一樣是一次固定的 HTTP POST,但 Filament 的表單操作實際上是透過 Livewire 元件內部的方法呼叫完成的,不一定真的存在這樣一個可以直接 POST 的路由,就算存在,這種測試方式也繞過了元件本身的驗證邏輯、狀態管理,測不準真實的互動行為。
test('admin can create news', function () {
asAdmin();
livewire(CreateNews::class)
->fillForm([
'title' => '測試新聞',
'content' => '內容',
])
->call('create')
->assertHasNoFormErrors();
assertDatabaseHas('news', ['title' => '測試新聞']);
});
這支測試直接把「建立新聞」這個 Filament 頁面元件當成物件操作:填表單、呼叫建立方法、驗證表單沒有出現驗證錯誤,最後再確認資料庫裡真的多了一筆對應的資料。這才是貼近使用者實際互動路徑、也真正驗證到底層邏輯的寫法。
測後台功能時,很容易寫出「驗證畫面上出現了某段文字」這種斷言,例如檢查有沒有出現「新增成功」的提示訊息。這種驗證不是沒有價值,但它驗證的是介面文字,不是動作本身。
如果介面文字寫對了、但背後的建立邏輯其實沒有真的把資料寫進資料庫,只驗證文字的測試依然會通過,因為它從來沒有真的去確認資料庫裡發生了什麼事。前面的匯出案例選擇驗證「檔案真的存在」,建立案例選擇驗證「資料庫裡真的多了一筆資料」,都是同一個原則的體現:測試後台操作,最終要驗證的是這個操作對系統狀態造成的真實影響,介面上顯示的文字只是這個影響的其中一種呈現方式,不能只驗證呈現方式而跳過驗證真正的影響。
回想你手上維護的後台系統測試,有沒有一支測試只驗證了「畫面上出現了成功訊息」,卻沒有真的確認背後的資料變化?如果把成功訊息的文字改錯,這支測試會不會因此失敗——如果不會,代表它從來沒有真的在驗證這段文字本身。
明天要看巢狀資源的測試——一個樹狀編輯介面,同時支援獨立入口模式跟內嵌顯示模式,這兩種模式分別怎麼測,以及測試裡怎麼快速建出多層的巢狀測試資料。