28 April 2014

上一篇我提供個人 TDD 的經驗給大家參考,這一篇來講它對面的事 -- 沒有自動化測試的程式。我是 TDD 的支持者,所以可以測的我都會想辦法測。那有沒有不適用 TDD 的程式呢?有的,經過這幾年的考驗,我發現有些程式不該花時間用 Unit Test 去解決。

1. 探索新領域

當你在研究一個全新的領域時,比方說你得開始研究 Lucene,要提供文章分類或是用關鍵字判斷用戶喜好,如果你完全沒做過的話,你第一眼看到 Lucene 的 API 保證傻眼,有太多的專有名詞,太多的新概念。這時候 TDD 幫不了你的,你得老老實實的看文件,開始寫些簡單的範例,東改西改的湊合著用,漸漸的才能拼出一個雛型。

有了雛型之後你才能了解來龍去脈,開始知道怎麼寫測試才好。對於完全未知的領域很難起手寫測試的。也是可以寫啦,只是大部份會在實驗過程中打掉,TDD 這時反而是絆腳石。

所以新領域的程式會這樣發展:亂實驗 -> 雛型 -> 補測試 -> 完工。對於這樣的發展,我的經驗是雖然可以完工但品質常常不好,因為畢竟是新學乍練、而且測試都是後來才補上,Test First 的優點都沒了。但我想學習新領域是沒有捷徑的,這時候品質真的要等到經驗夠了才能提升。

2. 遊戲

我的公司 Cubie 前身是遊戲公司,就那種 flash 的小遊戲。所以我個人也接觸過這個領域二、三年。我開始寫遊戲時也是把寫 java 的習慣帶過去,想用 TDD 開發。不過我馬上就撞牆了,遊戲界對 TDD 這種流程沒什麼著墨,相對應的工具少的可憐,整個社群著重在遊戲機構的設計,更真實的模型,更炫的聲光效果,更好的效能。對遊戲界來說這些才是生死關鍵所在。而且很多時候為了更好的效能,常常會放棄較為結構化的程式。跟 TDD 的目標 - 程式好讀好維護 - 有點背道而馳。

而且遊戲是個以畫面為中心的軟體啊,滿滿的 side effect,side effect 這麼多幾乎沒辦法寫測試。遊戲的開發有一部份是純數學/物理的運算,這些的確是可以測,而且很需要 TDD 來輔助確保不會算錯。所以到了後來我只剩純運算類還繼續有寫測試,而且只剩我一個人在寫,無法推行到其他遊戲開發者。最終就是大部份的遊戲程式都是靠人工測了。只靠人工測,bug 就是多,也難怪遊戲界通常要請很多測試員來除錯了。(當然有一部份原因是要測遊戲平衡)

3. GUI

UI 類的程式我現階段已放棄寫 Unit Test,不論是 web 還是 mobile。原因就是 UI 是 side effect,很難寫。可以硬寫,但是很難維護,因為 UI 流程改動一下就要改很久,投資報酬率太低。這部份如果要自動化測試的話,通常是做 Functional Test,而不是 Unit Test。不過 Functional Test 我們公司也是沒做自動化,只有人工測試。透過人工實際使用 app,測使用案例,也測 UI 有沒有異常。

沒有自動化測試,品質就比較難維持,bug 就會多,但如果開發者開始花精神維護 Functonal Test 測功能測 UI,那成本實在太傷,整天都在維護那些難寫的測試,正事都不用做了。

確保品質

沒自動化測試的程式,也沒專職的 QA 把關,我們公司的解法是靠 pair programming,這算是確保每一行程式,都是由兩位開發者產生和驗證過的。我不是說用 pair 就能取代 QA 和測試,只是 pair 對於降低 bug 出現率多少有點幫助。因為實行 pair,所以也省下 code review 的時間。

另外,對於不同的產品,我們做人工測試的時間也不同:

  • 後台伺服器:在 staging 伺服器確認功能後,就直接 rolling upgrade 正式機
  • Android App:確認功能後,發放給公司員工安裝,一到二天沒事就上線
  • iOS App:確認功能後,發放給員工安裝,三天到一週的測試時間後才會送審

server 的話幾乎都是 TDD 流程開發的,所以 CI 過了就差不多了,就算出了錯也可以很快修正再重新上線。而 Mobile App 的話我們測試寫的不多,因為大部份都是 GUI 的程式。我們小公司所以都是拿員工充當測試員,對於 Android 版的 App, 員工測完一兩天就上架了。Android app 如果出 bug,要重新上架只要 1 小時,所以我們也不是很在意零碎的小 bug。只有 iOS App 要人工測特別久。iOS 的 app 如果出包了,再送審還要等一到二週,那會很慘。所以 iOS 整體功能的測試時間拉的很長。

當然啦,這是因為現階段我們公司都是自行開發產品,所以出貨上架都可以自己決定。如果是接案的話大概沒有這麼自由的佈署時程了,做法也會不同吧。

小結

探索新領域、遊戲界、UI 層這三類的程式很難寫測試,或者是寫好後維護成本太高,所以現階段這些領域我就不用 TDD 開發了。我也順便介紹了一下我們公司人工測試的做法。而自動化 Functional Test 我們則沒做,因為我之前嘗試都沒有得到好的結果,希望未來能夠找到好的工具,在這領域上加強一些。不然只靠人工測試實在是蠻遜的。


回響

可以用 Tag <I>、<B>,程式碼請用 <PRE>