我的BDD物語1
從開始使用TDD之後一年多,發覺不管是解Bug還是做Enhancement,沒有寫Test就會覺得全身不對勁,在這段期間,也看到了許多TDD進階到BDD的分享文章,像是INTRODUCING BDD,最有感的應該是這篇WHAT’S IN A STORY?,看了之後發覺原來寫User Story是很簡單的,有固定的格式,也可以很好的描述出系統的行為。之前看到那種厚重的文件裡面內含的Use Cases,我心想,到底這種文件誰會來維護,一定不是Developer...,不是Develper維護的結果就是文件跟不上code,基本上這種文件都要準備的很完整的形式,是給某些走重裝軟體流程的團隊,而我們寫code的時間都不夠了,哪有時間在那邊改一堆奇奇怪怪的Word、Excel、PDF。而以BDD的方式來作,只要寫出如下的Story:就可以就寫Behavior Test,文件格式也很簡單,用普通文字檔就可以,也可以用Markdown之類的格式來呈現,在有需要與Product Owner或Feature Owner討論的時候就可以派的上用場,討論完馬上就可修改,寫Behavior Test時一想到其他Case也可以修改。
故事是這麼開始的
有了TDD的經驗與BDD的知識之後,我在開發N功能時就實際應用上去,N功能對我而言是有點莫名其妙的功能,感覺與我們系統的設計背道而馳,這部份我就不多說,總之,開了一次又一次的會,大概對實際需求有個譜,在還沒有開始寫Code之前,我就先寫出了一個又一個的User Story,其實撰寫User Story也沒辦法花太多時間,一開始大概一兩個下午斷斷續續就完成初版,由於系統裡還有很多面向,例如備份、升級、組態模板、事件、還有各式各樣的使用者行為,有些面向我也沒有實際接觸過,所以只能寫出User Story的Title。接下來開始寫Code之後,我的方式是每個User Story對應一個Class,每個Scenario對應一個Test Method,每個Scenario都代表User的一個行為,當然也有系統因為狀態變化的行為。以TDD的方式來做,當然就是先把Test寫好,然後再去修改Production code裡面的內容,來滿足Test的結果。這個作法的好處在開發時我體會到幾項:
- 一邊寫會一邊思考除了目前寫的Scenario之外,還有哪種不同的Scenario,如果想到新的,就在文件上加一個Scenario。接下來繼續做,這樣的好處是比較不會漏掉。
- 另外就是成為自己的程式碼的第一個使用者,基本上Test在做的事情,就是User透過Web UI或是CLI過來做的事情,如果沒有提供清晰的界面,方便不容易錯的參數,第一個遭殃的就是寫Test的自己。
- 減少把整個系統跑起來測試的時間,我們家的系統大到爆,基本上是沒有辦法在本機把系統所有元件跑起來,通常我沒寫Test的測法都是把jar丟到遠端機器上執行,然後操作UI看log。這樣子超沒有效率,以我們寫Backend的人來說,其實User的行為最後都是做資料的操作與運算,只要能夠用Test確保資料操作與運算都正確,到最後階段再測試與UI的整合就可以。
- 相較於以往都是對一般功能性的Class寫Test,有可能是要測試Class的某些運算邏輯,或是某些Business Process,對於不懂的人,或是過了一年半載再來看的人,簡直就是一頭霧水,用BDD來寫Test可以很容易看懂到底要跑哪一種使用者行為,而且這些使用者行為是不管內部程式架構怎麼改,都必須一直有效,除非產品本身的功能有所變化。 雖然開發初期就有體會到BDD的好處,不過為了要讓code可以看起來BDD一點,花了不少時間在對我們底層架構東摸摸西摸摸,還好前輩們寫了不少Test範例,很多一開始不知道如何使用的Entity,看了相關的Test寫法之後,也可以依樣畫葫藘,只可惜沒辦法用我們自家新一代的Test專用資源管理系統,光是花在資源管理的問題,我就不知道多花了幾個小時...要寫Test,把好用的Framework準備好也是很重要的呀!
從A Branch整合到B branch
我一直都在A branch開發,明明就是做同一版本的東西,一開始又分成Dev branch與Release branch,這我是沒啥意見,但是兩個branch之間沒有sync則是用Peforce的大忌!最後A branch要廢掉,要把所有開發的成果全部Integrate到B branch上,branch owner的策略就是讓Developer自行一個一個Change list(Change list是Perforce修改的單位),這個策略本質上就是把所有的複雜度交給Developer,然後再來讓QA開一堆bug來追Developer。我個人是不太喜歡啦,既然要用Perforce就應該套用Perforce的best practice才對。遇到這種狀況,我當然就是把所有在A branch的Change list全部Merge到B branch上,然後跑Test,全過!就...收工。4X的Scenario的Test都過了,有問題就交給QA發現吧,這次整合大概花費時間是一個下午不到。我的code被蓋掉了!
由於我很快的就從A branch到B branch整合完畢,接下來就是其他人整合自己開發的成果到B branch,某天下午,天色已近黃昏,我突然發現,我這個功能的Test在Jenkins上跑的自動測試失敗了!點進去Jenkins的頁面一看,這些Test我之前跑過都是OK的呀,看到失敗的Test,因為是BDD,就等同是使用者操作一樣的動作會失敗,大概有快一半!這下包了,難道是我無意識做了什麼要命的動作,馬上打開IDE看一下Source code,結果發現...我寫的code怎麼變成之前的模樣!結果用Peforce找出了真兇,原來是我們遠在印度的同事,把code從A branch整合到B branch時把我的code覆蓋掉了...接下當然又是一堆信件風暴來來回回,最後,只好請那位同事Backout他的整合成果,我只能說,還好我有Test,不然過了幾天Release給QA之後才發現就...什麼!要改ID!
這個N功能進了QA測試階段之後,主要流程幾乎沒什麼問題,當然也是有些字串顯示,或是沒有考慮到流程,這種狀況當然是會在User story與Scenario上多加幾筆,也寫對應的Test,最後的Scenario Test數量來到61個,老實說,Test的程式碼數量是比實際功能數量來得多,一方面是我們的Test Framework還沒做到很簡潔,另一方面就是一個User Story再配合系統當下的狀態,本來就會有各種Scenario,code的數量較多也是理所當然。結果在QA測到了最後,這個N功能有一個User Story的Scenario我們沒有考慮到,結果Feature Owner不太能接受,我當下還真的有點難受,我做對了95%以上的Scenario,但是這個並沒有做對,我想,我有一件最重要的事情沒有做到位:BDD裡面的驗收測試案例,是Poduct Owner、Developer、QA共同決定認可的。
還記得我前文並沒有提到我有將寫出來的Scenario一一的與Feature Owner確認。以我們部門的架構、座位的遠近,同事之間的合作程度,我完全有機會與Feature Owner做確認,不過我卻沒做到。或許做了還是會疏忽掉這個Scenario,但是沒做到這點就是不夠專業...
經過一番討論之後,後來得出了個把底層資料結構所用的ID換掉來解決這個問題,啥,換ID!每個地方做運算與比較都用到ID耶!看起來好像要花不少時間,但我其實並不太抗拒,因為我們有BDD裡面的驗收測試案例,就算要改的地方比較多,但是只要最好能跑過這61個Test就應該沒太大問題。結果最後以不修改告一段落...
再來一次,從B branch到C branch
同樣的歷史果然又上演一次,聽說在這之後的Branch Model向Perforce的Best Practice看齊~這次我們再忍耐一下吧,懷著這樣的希望,我再次的把B branch的Change list整合到C branch,C branch是新版本的產品,架構有不少變化,整合過去,原本N功能的Scenario Test也有一半以上有問題,不過大概花了一個上午的時間就...搞定了。看到61個Test全亮綠燈,心中有股事情就該是這樣的確定感...結語
這次使用BDD做Feature的開發,還真的學到蠻多的,好處與難處全都遇到了,對我自己而言,好處遠遠大於難處。另外- 與Product Owner(Feature Owner)確認BDD裡面的驗收測試案例
- 簡化Test的撰寫方式,讓驗收測試可以用更有表達性的方式呈現
沒有留言:
張貼留言