平常有在寫自動化測試案例並且執行迴歸測試的鄉民們,幾乎一定都會遇到一個問題:在沒有修改程式碼的情況下,為什麼有些測試案例有時候會過,有時候不會過呢?遇到這種狀況,相信鄉民們第一個念頭一定是:難道是遇到鬼,農曆七月不是已經過了?!除了遇到鬼這個可能的原因之外,應該還有其他更科學一點的解釋吧。
在還不用查看任何資料之前,大部分有寫過測試案例的鄉民們,應該隨便都可以找出幾個嫌疑犯。例如,測試案例的相依性(測試案例必須依照特定執行順序才會全部通過,只要前面的測試案例失敗,後面的測試案例就會被「帶屎(拖累)」跟著一起失敗)而導致這種時好時壞的靈異現象。還有timing也是很常見的問題,像是點選網頁上某個連結,等待若干秒之後期待會有什麼「好事(結果)」發生,但是等到天荒地老卻什麼事也沒發生 。
Teddy在開發軟體的時候,也經常會遇到測試案例時好時壞的問題,也累積了一些小技巧用來解決這些問題,但是從來也沒特別想過產生這種現象的根本原因可能有那些。幾個月前無意中讀到了Martin Fowler的這一篇《Eradicating Non-Determinism in Tests》(消除測試中的不確定性)文章,發現Martin Fowler已經幫大家整理好了,那我們這些後生晚輩就可以直接站在巨人的肩膀上看得更高、更遠了 。
***
還沒痊癒,就先隔離當遇到這種時好時壞的測試案例,請問鄉民們的第一個反應是什麼?直接把測試案例丟掉,還是嘗試修正?換個方式來問這個問題,假設你有一個朋友得到SARS,請問鄉民們該如何處置?人道毀滅(直接丟掉),這樣太慘忍了。想辦法醫治(嘗試修正),但是一時之間又不知道要用什麼藥可以治療SARS。搞不好藥還沒找到,就先傳染給其他人,那豈不是更慘。所以,遇到這種情況,第一件要做的事應該是把病人(有問題的測試案例)給關在負壓隔離病房(居家自我隔離也OK啦)。
什麼叫做「關在負壓隔離病房」?簡單的說,就是要把病人(時好時壞的測試案例)從正常人(正常的測試案例)裡面給挑出來。因為如果不這麼做,測試案例有時成功,有時失敗,久而久之開發人員就會想:啊,我們的測試案例就是不知道為什麼時好時壞,所以這一次的執行結果雖然失敗,但「此為正常現象,請安心服用」,不用管它了。原本測試案例如果執行失敗應該是要請開發人員找出程式中的問題(production code或是test code有問題),但如果把時好時壞的測試案例和正常的測試案例混在一起,時間久了之後開發人員就不再信任測試案例,因此這些測試案例就等於沒有作用。
知道了為什麼要隔離之後,接下來說明一下要如何隔離。根據Martin Fowler的說法,隔離的意思,是把時好時壞的測試案例從持續整合系統的「main deployment pipeline 」移除。這是什麼意思?用畫圖解釋比較快。
當開發人員把程式送交到版控系統(例如,SVN或Git)之後,版控系統送一個通知訊息給持續整合系統,觸發一次建構。在正常情況之下,持續整合系統被板控系統所驅動的每次建構會執行一個主要的建構流程,稱之為「main deployment pipeline 」。因為這個流程由好幾個建構工作,例如編譯、測試、靜態程式碼分析、打包程式等等所組成,整個流程串起來好像一個管線一樣,所以稱為deployment pipeline(因為持續整合的最終目的是希望能夠佈署軟體,所以叫做佈署管線)。
現在問題來了,如果測試案例中有那種時好時壞的測試案例,就不宜將它們留在main deployment pipeline中。但是又不能直接砍掉,所以就在持續整合系統中額外增加一個「quarantined pipeline」(隔離管線),把時好時壞的測試案例先移到這裡隔離起來。之後,可以設定讓持續整合系統在每次執行建構的時候,分別或同時執行main deployment pipeline與quarantined pipeline這兩個管線的建構工作。這種做法的大原則是,在main deployment pipeline上的測試案例全部都要通過,而在quarantined pipeline的測試案例如果不通過則可以暫時忽略。如此一來開發人員對於main deployment pipeline的測試案例還是持續保持著信心,而至於在quarantined pipeline的測試案例,則可以找時間再來修復。
***
Quarantined pipeline不是垃圾桶把時好時壞的測試案例移到quarantined pipeline的這種作法,有兩點要特別留意:
- 這種做法不是教大家把所有執行失敗的測試案例不分青紅皂白全部都直接移到quarantined pipeline,只有那種因為不明原因而時好時壞的測試案例才移到quarantined pipeline。關於那種每次執行都一定會失敗的測試案例,不是production code有問題,或是test code有問題,應該要找出問題加以修正。
- 移到quarantined pipeline只是一種暫時性權宜措施,不是把時好時壞的測試案例丟進來之後就不管它們了,還是要安排時間來修護。至於何時修正,可以由開發團隊自行決定。一種常見的做法是,鄉民們可以規定,例如quarantined pipeline裡面的測試案例最多不能超過5個,一但超過5個,團隊就必須安排時間來修復這些測試案例。修復完成的測試案例,就會從quarantined pipeline移回main deployment pipeline中。
***
友藏內心獨白:隔離和砍掉是不同的做法喔。
沒有留言:
張貼留言