選單

測試環境擷取郵件:在 CI 裡不要依賴外部寄信

測試環境擷取郵件是把寄信導向本機收件端,信件直接落成檔案或記憶體。本文說明為什麼持續整合不該依賴外部服務、並行測試怎麼隔離,以及失敗時要保留什麼。

發佈於

  • 持續整合
  • 測試郵件
  • 自動化測試

測試環境擷取郵件指的是把應用程式寄信的方向改成指向本機的一個收件端,信件不會真的離開這台機器,而是落成檔案或留在記憶體裡,測試再直接讀它。這麼做不是為了省錢,而是為了讓測試穩定、快速,而且不必把內容送到第三方。

為什麼不該在 CI 裡依賴外部寄信?

第一個理由是穩定。持續整合環境的網路限制通常比較嚴格,對外連線可能被限制、可能沒有出口,寄到外面的信有時成功有時失敗。一條偶爾紅一次的測試,很快就會被團隊忽略。

第二個理由是速度。真正寄一封信要經過對方的伺服器,對方回應的時間不受你控制;一個測試多等幾秒,一百個測試就是好幾分鐘。把信留在本機,等待時間幾乎消失。

第三個理由是隱私與成本。測試信裡常有暫存連結、內部主機名稱與範例資料,這些內容沒有必要離開你的環境。另外,寄信通常有配額,測試跑得越勤、用量越大,完全沒有必要把配額花在這裡。

第四個理由是可控性。本機收件端讓你能查詢「目前為止寄出了幾封」、能取得原始郵件內容、能在測試結束後清空;這些能力在對外寄信時都不存在。

信件落到哪裡?三種常見取法

第一種是檔案。每封信寫成一個檔案,測試讀檔解析。它的好處是失敗時可以直接打開來看,除錯非常直覺;缺點是需要處理檔名衝突與清理。

第二種是記憶體。信存在收件端的行程內,測試透過查詢取得。它最快,也最容易做到每個測試各自隔離;缺點是行程結束就消失,事後無法回看。

第三種是資料庫。信件寫進一張表,測試用查詢條件取出。它適合需要跨步驟檢查的流程,也方便統計;缺點是多了清理與並行存取的考量。

三種可以並存。常見的作法是主要流程用記憶體以換取速度,同時把原始郵件留在檔案以備除錯。

並行測試要怎麼隔離?

隔離方式 做法 適合情況
每個測試一個地址 每次執行使用不同收件地址 最通用,缺口最少
每個行程一個收件端 不同測試行程連到不同實例 測試之間完全獨立
依寄件內容過濾 用主旨或內文關鍵字挑信 難以產生唯一地址時
執行前後清空 開始與結束都重置收件端 單一序列執行的套件

只靠「執行前清空」在並行環境下一定會出問題,因為別的測試可能在你清空之後、查詢之前又送了一封。最保險的作法仍然是每個測試一個地址,並讓地址在測試名稱的基礎上產生,這樣失敗訊息裡就能直接看出是哪一條測試。

為什麼不能等固定秒數?

因為寄信是非同步的。應用程式把信交給寄信伺服器之後就繼續往下跑,信什麼時候被收下來不由測試決定。固定等待的問題是它同時太長又太短:多數時候浪費時間,少數時候不夠而失敗。

正確的作法是輪詢:反覆查詢收件端,直到信出現或達到上限。達到上限時要留下現場,包括目前收到的所有信件、應用程式的寄信紀錄,以及當下的時間,這樣才能判斷是根本沒寄出、寄到別的地方,還是內容不符。

另一個容易犯的錯誤是把「收到信」當成通過條件。真正要檢查的是信裡的內容:連結指向哪個環境、變數有沒有被換掉、主旨是否符合語系。只確認信存在,等於只測了流程的一半。

擷取郵件還需要驗證哪三件事?

第一件是「有沒有寄」。這聽起來理所當然,但最常見的失敗其實是事件根本沒有觸發,而測試卻在等一封永遠不會出現的信,於是把時間浪費在等待而不是診斷上。

第二件是「寄給誰」。收件者是否為當下應該收到的那個人,換綁、改資料、多帳號等情境都會讓這裡出錯。收件端擷取的好處是你能直接比對實際的收件者欄位,而不是只看應用程式日誌裡記錄的字串。

第三件是「內容是否為當下版本」。模板改版後舊的斷言常常還留著,測試照樣通過,但你保證的其實是一個已經不存在的版本。把模板版本一起記進斷言,可以讓這類沉默的落差浮現出來。

這三件事都屬於流程層面的檢查,與信箱驗證測試裡的案例清單是互補的:一邊確認信被正確產生,一邊確認使用者走完流程後狀態正確。

在本站的臨時信箱裡做人工複核

自動化之外的場合,仍然需要有人實際看一次信在收件匣裡長什麼樣子。在本站的臨時信箱裡產生地址,手動觸發一次流程,就能確認排版、連結與按鈕在真實收信端是否正常;這些是自動化斷言不容易覆蓋的部分。

這類地址僅供測試與接收註冊驗證信,不能當作真實身分或正式聯絡管道;請不要在裡面放入任何真實使用者的資料。

給開發者:隔離、輪詢與保留現場

把上面幾條收斂成實作守則:

  • 收件端只綁在本機。不要讓測試有機會把信送到外部服務,這應該由設定決定,而不是靠測試自律。
  • 每個測試一個地址,命名帶上測試識別。地址唯一,取信就不需要猜。
  • 輪詢到出現為止,並設上限。上限存在的目的是讓失敗快速發生,而不是讓它更慢。
  • 斷言內容,不要只斷言數量。收件數量容易受重複投遞影響,內容才是你真正要保證的東西。
  • 失敗時保留原始郵件。一封沒有保留的失敗信件,第二天幾乎無法重現。
  • 清理要涵蓋通知類的副作用。擷取郵件讓你不會真的打擾到人,但資料庫裡的狀態仍然要復原。

下一步

先把測試套件裡所有對外寄信的依賴找出來,改成指向本機收件端,並替每條測試換上獨立地址。當流程中出現驗證碼時,可以接著讀OTP 自動化測試;想了解預發環境常用的全收設定,則可以參考全收信箱是什麼。

繼續閱讀

臨時信箱(一次性信箱/10 分鐘信箱)相關文章