iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
Software Development

同一套 Laravel 系統,測試怎麼寫才不會說謊系列 第 9

Day 09:Filament 後台測試怎麼寫——測「動作有沒有真的發生」而不是「畫面長什麼樣」

  • 分享至 

  • xImage
  •  

前言

「後台是用 Filament 這種管理面板套件開發的,測試也要照一般 HTTP 頁面那樣打請求、看回應內容嗎?」

答案是不行——至少不是最有效的方式。Filament 這類後台管理套件,介面背後是用 Livewire 元件組成的,使用者在畫面上點的每一個按鈕、填的每一個表單,最終都是在跟一個 Livewire 元件互動,不是傳統的表單送出、整頁重新整理。這代表測試後台功能時,要測的重點不是「這個 HTTP 請求回傳了什麼畫面」,而是「這個操作有沒有真的觸發該發生的動作」

先說清楚:這篇只講測試手法本身,不會深入教 Filament 這套後台框架怎麼開發,重點放在「怎麼驗證一個後台操作真的有效」這件事。

今日目標

  • 理解為什麼測 Filament 後台不能沿用一般 HTTP Feature 測試的思路
  • 看這個系統怎麼用 Livewire 測試工具直接操作後台元件
  • 認識「驗證動作有沒有真的發生」跟「驗證畫面顯示了什麼文字」是兩種不同層級的驗證
  • 學到一個具體案例:測試一個匯出功能,怎麼驗證真的有檔案被產生出來

Livewire 元件不是普通的 HTTP 端點

一般網頁的一次互動,通常對應到「送出一個 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 檔案

這種驗證方式回答的問題是:「這個匯出按鈕背後串接的邏輯,真的有把資料寫成一個檔案」,而不是「畫面上顯示了『匯出成功』這幾個字」。後者只驗證了介面文字,前者驗證了功能本身確實運作。

❌ 用一般 HTTP 測試思路硬套 Filament 後台

test('admin can create news', function () {
    asAdmin();

    post('/admin/news', [
        'title' => '測試新聞',
        'content' => '內容',
    ])->assertRedirect();
});

這種寫法假設後台表單送出跟傳統網頁一樣是一次固定的 HTTP POST,但 Filament 的表單操作實際上是透過 Livewire 元件內部的方法呼叫完成的,不一定真的存在這樣一個可以直接 POST 的路由,就算存在,這種測試方式也繞過了元件本身的驗證邏輯、狀態管理,測不準真實的互動行為。

✅ 直接操作 Livewire 元件本身

test('admin can create news', function () {
    asAdmin();

    livewire(CreateNews::class)
        ->fillForm([
            'title' => '測試新聞',
            'content' => '內容',
        ])
        ->call('create')
        ->assertHasNoFormErrors();

    assertDatabaseHas('news', ['title' => '測試新聞']);
});

這支測試直接把「建立新聞」這個 Filament 頁面元件當成物件操作:填表單、呼叫建立方法、驗證表單沒有出現驗證錯誤,最後再確認資料庫裡真的多了一筆對應的資料。這才是貼近使用者實際互動路徑、也真正驗證到底層邏輯的寫法。

驗證動作發生,比驗證畫面文字更可靠

測後台功能時,很容易寫出「驗證畫面上出現了某段文字」這種斷言,例如檢查有沒有出現「新增成功」的提示訊息。這種驗證不是沒有價值,但它驗證的是介面文字,不是動作本身

如果介面文字寫對了、但背後的建立邏輯其實沒有真的把資料寫進資料庫,只驗證文字的測試依然會通過,因為它從來沒有真的去確認資料庫裡發生了什麼事。前面的匯出案例選擇驗證「檔案真的存在」,建立案例選擇驗證「資料庫裡真的多了一筆資料」,都是同一個原則的體現:測試後台操作,最終要驗證的是這個操作對系統狀態造成的真實影響,介面上顯示的文字只是這個影響的其中一種呈現方式,不能只驗證呈現方式而跳過驗證真正的影響

今日思考題

回想你手上維護的後台系統測試,有沒有一支測試只驗證了「畫面上出現了成功訊息」,卻沒有真的確認背後的資料變化?如果把成功訊息的文字改錯,這支測試會不會因此失敗——如果不會,代表它從來沒有真的在驗證這段文字本身。

今日重點回顧

  • Livewire 元件的互動模型不是傳統的表單送出,測試時要直接對元件下指令,不是模擬固定路由的 HTTP 請求
  • 驗證後台操作的重點是「動作有沒有真的發生」(檔案真的產生、資料庫真的寫入),不是「畫面上出現了什麼文字」
  • 匯出功能的測試案例示範了怎麼用假硬碟驗證真的有檔案被產生出來
  • 只驗證介面文字的測試,測不出背後邏輯是否真的正確運作——文字寫對,不代表邏輯也對

明日預告

明天要看巢狀資源的測試——一個樹狀編輯介面,同時支援獨立入口模式跟內嵌顯示模式,這兩種模式分別怎麼測,以及測試裡怎麼快速建出多層的巢狀測試資料。


上一篇
Day 08:Feature 測試基礎——一個 HTTP 請求怎麼測到「畫面對不對」
下一篇
Day 10:巢狀資源測試——樹狀編輯介面的獨立模式 vs 內嵌模式怎麼測
系列文
同一套 Laravel 系統,測試怎麼寫才不會說謊14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言