天天看點

《驗收測試驅動開發:ATDD執行個體詳解》—第2章2.2節結對完成第一個測試

本節書摘來自異步社群《驗收測試驅動開發:atdd執行個體詳解》一書中的第2章2.2節結對完成第一個測試,作者【德】markus gärtner,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

2.2 結對完成第一個測試

驗收測試驅動開發:atdd執行個體詳解

tony和alex開始結對寫實作代碼并對第一個測試進行自動化。alex已經為網站做好了第一個布局,他向tony介紹了他的想法。

alex:嘿,tony,你有興趣看看停車費電腦的進展嗎?

tony:其實我想跟你結對兒,對第一個測試進行自動化。

alex:哦,太好了,你從哪個開始的?

tony:代客泊車,我花了30分鐘引入了第一個測試,過來之前我剛把第一個挂起的執行個體送出了。

alex:很好,我先給你看看我這邊的完成情況。

alex給tony展示了他對頁面布局的初始設計(見圖2-3)。

《驗收測試驅動開發:ATDD執行個體詳解》—第2章2.2節結對完成第一個測試

2.2.1 初始化

alex:我設計由下拉菜單展現不同的停車場。日期可以直接由輸入框填入字元串,或者用月曆控件選擇日期。停入和離開的時間由文本輸入,有一個單選按鈕決定上午還是下午。當計算按鈕按下之後就會顯示估算的停車費。

tony:看起來不錯。看看這個,現在這些步驟定義還是挂起的,我們需要解決它們。

alex:好的,這些看起來并不複雜。我們從下拉菜單選擇停車場開始吧。這裡我用的id是parkinglot,是以從下拉菜單選擇合适的值一步就可以做到,就像這樣。

alex實作了lib/parkcalc.rb檔案中的select方法,如程式清單2-11所示。

程式清單2-11 從下拉菜單中選擇正确的停車場

tony:好的,看起來很直覺。我從id為parkinglot的元素上選擇了傳入參數代表的停車場。很好,那麼輸入停車時間呢?

alex:這需要更多的思考,我們用ruby裡的hash(散清單)來實作吧。以後你就可以擴充這些停入和離開的日期和時間值,然後模拟你所需要的所有不同的時長。

tony:那咱們應該怎麼做呢?

alex:基本上我們根據傳入的時長字元串查找實際的停入日期、停入時間、上午還是下午、離開日期、離開時間以及離開是上午還是下午的值,并将它們填入頁面。這6個值代表了我構造的表單中的6個項。不過我們先來定義這個散清單(hashmap)。

alex在parkcalcpage類的開頭構造了一個時長的散清單(見程式清單2-12)。

程式清單2-12 記錄時長和實際日期時間的散清單

tony:兩個@說明durationmap是一個類變量,對吧?

alex:對的,現在我們要從散清單中得到我們關心的那6個值,我示範給你看如何從散清單中取值。

alex開始實作enter_parking_duartion函數(見程式清單2-13)。

程式清單2-13 從durationmap得到表單的6個參數

alex:現在,讓我們把這些值填入表單。我們從停入日期和時間開始。

如程式清單2-14所示,alex繼續擴充這個方法,填入停車的時長。

程式清單2-14 将停入日期和時間填入對應的表單項

tony:你能解釋一下嗎?我看不懂最後一行。

alex:我解釋一下這裡的細節。首先我們以時長為鍵值從散清單中取出6個參數,然後我們填入相應的停入日期和時間。

tony:對,這很直覺。但是最後那行亂七八糟的東西是幹什麼的?

alex:我用它來定位單選按鈕。這是個xpath路徑,表示單選按鈕所在位置和它的值。它告訴驅動程式點選名為“startingtimeampm”且值為輸入參數的按鈕。

tony:我希望能把它放在别的地方。它包含太多技術細節,不适合放在這個相對抽象的函數裡。

alex:我想你是對的,tony。我們把它記下來,先完成這個函數再說。離開日期和時間還沒有呢。和停入時間類似。不過我們先看看現在能否正常運作。

alex開始執行這個測試,alex和tony一起看着浏覽器視窗被打開,進入停車場計算頁面,填入停車場、停入日期和時間值。最後浏覽器被關閉,運作結果顯示出來。

tony:看起來不錯,我們繼續處理時長吧。我們還需要填入離開日期和時間。

alex:當然,代碼和填入停入日期和時長類似。我們把代碼複制、粘貼過來,然後改一下變量名。如果這能運作,我們再回過頭來清理代碼。

alex繼續向函數中添加代碼,填入離開日期和時間(見程式清單2-15)。

程式清單2-15 在剛才的函數中加入離開日期和時間

tony和alex運作這些步驟,檢查是否正确填入了離開日期和時間。

alex:很好,能運作。我們現在來清理吧。這兩部分代碼看起來真的很類似。咱們把它放入一個單獨函數中吧。

alex和tony寫了一個新函數用來填寫停入或離開的日期、時間,并逐漸替換了原函數的實作。每做一點小的改動他們都會驗證第一個測試還能正常運作。他們完成後,代碼如程式清單2-16所示。

程式清單2-16 将填入停車時長抽取為單獨函數

alex:現在,我們來看一下如何提取那些怪異的xpath路徑。

tony:把它聲明為一個常量表達式如何?

alex:我也是這麼想的。同時我還想把其他固定的字元串也放入變量裡,這樣将來我們就可以很容易地修改它們了。我們一個一個來提取吧。我們先來消除掉xpath。我們需要給這個變量取個名字,你說叫什麼好呢?

tony:叫"ampmradiobuttontemplate"如何?

alex:我沒意見。我們以後是不是可以把日期和時間字元串也放進timetemplate和datetemplate?

tony:聽起來不錯。我們同樣可以把字首放入startingprefix和leavingprefix.

alex:對的,我還想把停車場的id也放入一個常量中去。

tony:現在看起來就很好了。

程式清單2-17展示了parkcalcpage類在alex和tony提取常量之後的最終版本。現在,初始化步驟就完成了。

程式清單2-17 parkcalcpage初始化步驟的最終版本

2.2.2 檢查結果

tony:現在我們來檢查一下輸出。我們還沒有點選你在表單裡放的calculate按鈕,并且我們需要從頁面中擷取費用的計算結果。

alex:當然,我們先把pending語句從步驟定義中去掉,這樣我們的定義的then部分就可以運作了。

tony: 噢!我差點就把這個忘了,要不然我得花半天時間才能搞清出了什麼毛病。

alex:這就是結對的好處,不是嗎?

tony:那麼現在我們可以把pending語句從檢查中去掉,然後我們來實作它。

alex:好的。現在我們來看看怎麼檢查正确的價格。首先,我們需要點選計算按鈕。我想把這作為第一步加入parking_costs函數,放在傳回費用之前。之後我們需要等待頁面載入新的值。然後我們擷取記錄費用的元素并傳回它。

alex實作了parking_costs函數,見程式清單2-18。

程式清單2-18 檢測代碼的初始版本

tony: 那個常量10000是幹什麼的?

alex:那是個逾時值。驅動最多等待10秒鐘,要麼新頁面成功載入,要麼測試會失敗。

tony:現在我們來清理一下這些亂糟糟的代碼。我建議同樣把xpath提取到一個常量中。

alex:首先,我們看一下是否能正确運作。我們來運作一下測試。

alex和tony啟動了測試,看着它執行了停車場費用計算,最後在指令行中顯示綠色,代表所有代碼工作良好(見程式清單2-19)。

程式清單2-19 第一個代客泊車測試的指令行輸出

tony:很好,測試通過了。在我們做任何修改之前,首先送出一下代碼,這樣将來我們可以復原我們所做的任何修改,以防萬一嘛。

alex:好主意。

alex和tony把他們的成果送出到版本控制系統。

alex:現在我們回到你的建議。想法很好,但是我想先把這個函數分成兩步。第一個函數用來點選“送出”按鈕并等待頁面載入。第二個函數會取到算好的費用并傳回。我寫給你看我是什麼意思。

alex從最初的parking_costs函數提出兩個函數(見程式清單2-20)。

程式清單2-20 将兩個步驟重構到各自函數後的檢查代碼

tony:現在我們來把定位費用元素的xpath路徑移到常量中去。

alex:既然要做這個,不如把“計算”按鈕的名字也用一個有意義的變量名表示好了。

tony: 現在,最後再跑一遍測試,然後我們就可以把代碼送出到源代碼庫裡了。

tony和alex看着測試運作通過了。他們将檔案送出到了代碼庫。程式清單2-21展示了step_definitions/valet_steps.rb的最終内容,程式清單2-22是lib/parkcalc.rb的最終内容。

程式清單2-21 代客泊車第一個測試步驟定義的最終版本

程式清單2-22 第一個測試parkcalcpage類的最終代碼

本文僅用于學習和交流目的,不代表異步社群觀點。非商業轉載請注明作譯者、出處,并保留本文的原始連結。