一條新流程上線後,外接第二螢幕停在上一個畫面——交易的另一方看不到當前狀態,主畫面卻一切正常、沒有任何錯誤浮現。漏通知的根因在機制,換誰開發都會再發生;驗證邊界則劃在出口——斷言送出的資料流與時序,裝置端的渲染交由裝置自己的系統驗證。

觀察

主裝置之外還有一面外接第二螢幕——面向交易另一方(例如顧客)的畫面,主畫面的狀態要同步過去。同步機制有兩種形態:

形態例子特性
訂閱驅動本地清單變動 → 自動推送資料流動就通知,不會漏
顯式呼叫某流程完成後手動推送一次每開一條新流程都要記得補一筆,容易漏

漏通知 bug 的成因:訂閱掛在「本地清單」的變動上,但有一條新流程走的是「遠端資料直接進入結帳」——資料不經過本地清單,訂閱永遠不觸發;而顯式呼叫沒人記得補。這是訂閱盲區:訂閱的資料源沒涵蓋所有會改變顯示內容的路徑。第二螢幕停在上一個畫面。

修復後補的驗證:所有送往第二螢幕的訊息都經過單一出口,測試注入一個錄音假件攔下每筆訊息(動作類型+內容),斷言序列——進結帳要推「畫面切換+品項清單」與「付款資訊」;完成時推「完成」;離開才推「清除」;且**「完成」必須先於「清除」**(順序顛倒時另一方看不到交易結果畫面,這是明文的時序約束)。

判讀

  1. 顯式呼叫是結構性風險點,可以被系統性審查。這份審查是一張可窮舉的清單:列出所有「會改變第二螢幕應顯示內容」的流程,逐一檢查它的資料走訂閱路徑、還是需要顯式推送。清單窮舉取代開發時的臨場記憶。

  2. 驗證邊界劃在「送出了什麼」。第二螢幕是另一個執行環境(甚至另一個引擎),它怎麼渲染不是這個測試套件能觸及的。正確的可測物是出口處的訊息流:內容、順序、時機。裝置端的渲染屬於另一個系統的職責。

  3. 序列斷言強於存在斷言。只斷言「有送完成訊息」抓不到「完成在清除之後」這種順序錯誤——而順序錯誤的使用者體驗傷害(看不到結果畫面)不亞於漏送。對有時序約束的訊息流,斷言用索引比較(完成的位置 < 清除的位置),而非個別存在性。

策略

  1. 收斂出口:所有外送訊息經過單一方法,測試才有唯一的攔截點。出口分散的程式先重構再談驗證。
  2. 錄音假件:以假件替換傳輸層,記錄(動作、內容)序列供斷言;不 mock 到業務層——業務到出口之間的編排正是要驗的對象。
  3. 時序約束寫成斷言:程式註解裡「A 必須在 B 之前」的每一句話,都應該有一條測試用索引比較把它鎖住。
  4. 長期方向:把顯式呼叫收編為訂閱。每多一條訂閱驅動的路徑,就少一個「記得補推送」的人為環節。訂閱化是消除這類 bug 的結構解。

下一步路由