缺它不可!靈活運用 Firefox OS Gaia 的單元測試

單元測試一直以來都是確保軟體品質的一種方式,在日益錯綜複雜的軟體中更是重要。Firefox OS 的應用層 Gaia 理所當然的也由單元測試來確保軟體品質。設置妥當後,當你打開任意編輯器對 Javascript 檔案編輯,並且按下『Save』的那一刻,unit test agent 就會默默的被喚起,針對您的修改一項項的進行檢測。當所有測試項目都妥當的通過之後,您將會看到一個優雅的圖示跳出來,告知你的測試均已通過。

Gaia 的單元測試將會針對修改的部份執行該部份的單元測試,可確保修改的時候所有的測項都可以通過。錯誤的時候當然也會跳出個讓你很難忽視的紅色圖示,提醒你本次修改沒有通過測試。

要如何設置 Gaia 的單元測試環境呢?首先你會需要以下環境:

  1. node.js
  2. Firefox nightly
  3. Gaia 開發環境

因為本文重點是單元測試環境,上面環境的安裝方法就不再贅述。準備好上面的環境後,切換到 gaia 目錄,鍵入以下的指令即可執行 test agent server

接下來則需要建立 gaia 除錯環境,請開另外一個終端機視窗鍵入下面指令(本步驟將會建立 debug 版本的 gaia profile)

最後把 firefox nightly 套用由 DEBUG=1 make 生成的 profile 檔即可執行並完成設定

注意!如果你在 Mac OS 上面開發,profile 目錄必須使用絕對路徑。

這樣就設定完成了,你可以打開已經有撰寫單元測試的 javascript 檔案如 gaia/apps/calendar/js/app.js,修改之後儲存,就會看到相關的單元測試開始執行了!

如何運作?

其實運作原理很簡單。 gaia 利用 node.js 來監控檔案系統的變化,並且利用 websocket 通知 nightly browser 要執行哪個單元測試檔案,nightly 執行完畢後,再把結果回傳給 node.js。最後再由 node.js 發出 notification 後,就是使用者看到的通過或失敗的測試通知囉!

既然 node.js 也是 javascript 的執行環境,為什麼不直接在 node.js 裡面執行單元測試呢?主要的原因是 Firefox Nightly 是一個接近 Firefox OS 的運行環境,也有些 API 在 Firefox nightly 才可以使用。所以在 Firefox nightly 裡面跑是比較合理的方式。

撰寫新的單元測試

看完了如何執行單元測試,那如果加了新功能要加入單元測試要怎麼作呢?正巧最近修改了 Gaia 的 Calendar app,為其加入 offline 的錯誤訊息的 Bug 809537 就需要為離線功能加入單元測試。在這個 bug 裡面我新增了兩個需要測試的部份:

  1. 新的 Errors View,用來顯示主頁的錯誤訊息
  2. caldav provider 裡面的 getAccount, findCalendars, syncEvents, createEvent, updateEvent, deleteEvent 新增偵測離線狀態的功能,當離線時 callback 會帶一個錯誤訊息。

Errors View 繼承自 View (js/view.js),其中最主要的功能是對處理來自 syncController 的  “offline" event,當 handleEvent 收到 “offline" 之後,會採用繼承自 View 的 showErrors 來顯示錯誤訊息,摘要重要的源碼如下:

針對 caldav provider 的修改,則是新增了 bailWhenOffline 在 offline 的時候新增一個 Error 並且作為 callback 的參數傳回。比如說下面的 findCalendars 就會先確認如果目前是 offline 就不會 request service。

Erros View 裡面,最需要測試的是 handleEvent 到 showErrors 是否正確的傳入了 { name: “offline" },而 showErrors 已經在 view_test.js 裡面測試過了不需要重複測試,所以測試的方法是作一個 Mock 的 showErrors function 塞入原本的 Errors View 物件內,如下圖所示

原本的 showErrors 會在手機上顯示錯誤訊息,但我們用 Mock 的 showErrors 之後就只會把傳入的 error name 直接 assign 到 errorName 裡面,如此一來我們對 syncController 發出 “offline" 事件,再確認 errorName 最後是不是拿到了 “offline" 來判斷 handleEvent 是否正常的運行。

至於 offline 訊息基本上是從 navigator.onLine 這個屬性得知的,所以在撰寫程式的時候我們把偵測 offline 的功能封裝在 app:offline() 裡面:

在執行單元測試的時候動態的把原本的 offline 儲存到 realOffline,接著塞一個每次都會回傳 true 的 offline(),如此一來就可以測試離線狀況時上述的 function 如 getAccount, findCalendar 會不會在 callback 裡面帶入 offline error 的錯誤,舉個測試 getAccount 離線狀況的例子:

我們將 Mock 的 offline function 替換進去,並且執行 getAcount,並且確定 cbError.name 是 offline 就可以確認我們加入的功能是可以正常運作的了。

感謝單元測試以及 Javascript 的動態特性!

我們可以在測試的時候非常容易的替換一些 Mock 物件進去來達到單元測試的效果。而且可別小看這些單元測試,當你的程式日益複雜的時候,這些單元測試就是保證軟體品質的第一道防線,也會讓開發的時候感到更加安心喔。

 

 

您可能也會喜歡

目前找不到相關文章