[30天快速上手TDD][Day 25]BDD - TDD from BDD
前言
前兩篇文章介紹到了,為什麼需要 BDD 來輔助我們進行 TDD ,原因是需求、 user story 與 acceptance test cases 都是透過 DSL 來描述,這離最後要 implement 的程式碼還太遙遠,導致無法從驗收測試案例的描述,簡單的轉換到 TDD 的開發流程,這中間的 gap 太大。
上篇文章介紹的 BDD 工具是 SpecFlow ,也稍微介紹了如何安裝,以及其 feature 檔中 feature 與 scenario 描述的相關注意事項,及其與 user story/acceptance test cases 的對照。
更帶到了如何透過 scenario 來定義清楚 acceptance test cases ,再從 scenario 定義出對應到 testing 的 3A 原則。
接下來這篇,就承接著上篇文章,用預設的 feature 與 scenario ,透過 TDD 的方式來完成一個加法器。
TDD Start
@SpecFlow 1.9.0 之前版本
第一步就先把原本的 Step 中內容刪掉,執行測試,將測試結果內容中的 Step 程式碼,放到 Step 中。執行時的錯誤訊息,如下圖所示:
將錯誤訊息中的提示,貼到 Step 檔後,如下圖所示:
上述這是 SpecFlow 1.8 版的建議方式,但 1.9.0 以後的版本,不用這麼麻煩了,接下來介紹 1.9.0 以後的版本,怎麼樣可以更快產生對應的 Step 檔,而不需要先執行錯誤,再自行複製貼上。
@SpecFlow 1.9.0 以後的版本
打開 Feature 檔,可以看到當 Scenario 中,若無對應的 step 描述,則會顯示出不同顏色,如下圖紫色的區塊:
若 feature 上仍有尚未定義的 step,則點滑鼠右鍵, menu 中就有Generate Step Definition
的選項。
點選後 Specflow 會自動判斷,該 feature 檔上還有哪些尚未定義的 step ,就像 VS2010 自動產生單元測試案例一般的畫面,如下圖所示:
上面有兩個選項:
-
Generate
:可直接產生對應的 step 檔案到測試專案中 -
Copy method to clipboard
:將對應的 step 檔案內容,複製到剪貼簿
產生完 Step 檔之後, scenario 的部份就會變成白色的了,如下圖所示:
這個檔案就會跟之前的版本一模模一樣樣。
TDD 的第一步
了解 feature 與 scenario 之後,我們的目標物件為 Calculator 。
針對 Feature , 建立我們的測試目標: Calculator 。並透過 Visual Studio 的產生功能,直接幫我們產生對應的 class 到 AtmOperation 的 project 中。如下圖所示:
接著第一個 Given 為『輸入數字50到 calculator 』,這邊我們的設計,就是想辦法符合 Scenario 的 Step 就對了。所以針對 Calculator ,新增一個 FirstNumber 的屬性,並設定為 50 。如下圖所示:
接下來,第二個 Given 為『輸入70到 calculator 』,這邊新增一個 SecondNumber 的屬性,並設定為 70 。如下圖所示:
接下來,應該針對 When 來設計,[When(@"I press add")],當我按下 add 時,所以這邊為 Calculator 新增一個 Add 的方法。如下圖所示:
最後,針對 Then 來驗證結果。 Scenario 上寫的很清楚,結果應該為 120 。所以這邊為 Calculator 新增一個 Result 的屬性,並驗證其值是否為 120 。如下圖所示:
到這,我們幾乎只是一直在用 Visual Studio 內建的產生類別、屬性跟方法的功能,一點都不難吧。類別、屬性與方法的命名,也會完全符合 scenario 的情境與意義。
ok,我們針對 Calculator 加法的 Feature , 針對兩個數字的相加這個 Scenario ,已經寫完我們的測試程式了,執行一下測試吧!
碰!紅燈!放個煙火慶祝一下,我們已經進入 TDD 循環的第一個步驟:紅燈。寫一個一開始會執行失敗,但又符合測試目標物件行為的測試程式。
看一下詳細的測試結果資訊,可以發現兩個 Given 都是 done ,錯誤發生點是在 When I press add 。如下圖所示:
在 Scenario 上偵錯
接下來,神奇的地方要來了,我們直接在 feature 檔上,scenario中的 When 部份加上中斷點。是的,你沒看錯,就是在 feature 檔案上新增中斷點。
接下來用偵錯測試的模式執行測試, When 的時候就會中斷,如下圖所示:
按下 F11 ,可以進去 Step 的程式中,如下圖所示:
再進去 Add 方法中, YES !! 總算看到我們的 production code 了,Add 方法中,還沒有實作相關的內容,所以測試會拋出 exception 。如下圖所示:
接下來,我們要想辦法,滿足 Scenario 的需求,當 FirstNumber 為 50 ,而 SecondNumber 為 70 時, Result 結果應該是 120 。
所以 Add 的方法內容,要滿足這個需求,我們做了以下的設計:
看起來很 ok ,接下來再執行一次測試,可以看到測試結果是綠燈了!而且,在詳細的測試訊息中,可以在『標準主控台輸出』中,看到 Scenario 的執行結果,測試程式就像說故事一樣,表達了 Calculator 的一種行為。如下圖所示:
到這邊,我們已經先使用 BDD 來描述物件行為,並自動產生 feature 中, Scenario 對應的測試程式。接下來透過 TDD 的方式,來執行測試與開發實際的程式。
小結
或許,您會覺得目前這樣的程式,很沒有彈性,如果需要再新增第三個數字,第四個數字,該怎麼辦?您可以有兩個方式:
- 重構 Calculator ,但重構過程中,仍須滿足已經存在的測試程式。
- 等真的有該需求出現時,再來滿足需求後,重構程式。
重構的部份,相信讀者朋友們經過前面一系列的洗禮,應該可以駕輕就熟了。如果想複習一下的朋友,請參考前面 Day9 ~ Day19 的文章。
筆者的心得是:
原本練習 TDD 時,總覺得 test cases 不夠精準,無法呈現 domain 的行為,而 QA 或 PM 所設計的 test cases ,又無法與測試程式作結合。
BDD 把最艱困的一個阻礙點打通了,目標物件的行為,可以透過 Feature 來與 User Story 或 Use Case 結合,透過 Scenario 來產生測試程式的外框與繫結,可以讓測試程式就像在描述 Scenario 般一樣自然。
整個概念有點類似下圖所示:
嚴格來說,上圖應該加上ATDD的stage,會更為清楚。不過這邊僅當示意簡圖。
下一篇文章,我們會為 BDD 做個總結,讓讀者朋友可更清楚的了解 BDD 在整個開發流程中的定位。
blog 與課程更新內容,請前往新站位置:http://tdd.best/