Feb. 21 10:57~12:46
Cucumber的初學者首先會遇到環境設定的問題,在〈在IntelliJ IDEA使用Cucumber(上)〉與〈在IntelliJ IDEA使用Cucumber(下)〉已經介紹了如何設定環境,接下來要談另一個常見的問題:「如何把scenario的每一個step對應到一個step definition程式碼?」
***
假設鄉民們要開發會計系統或門市銷售系統,其中有一個「開發票」功能。發票分成三聯式(公司報帳使用)與二聯式(個人使用)。三聯式發票會顯示含稅金額(tax included price)、未稅金額(tax excluded price)、稅金(VAT,加值型營業稅),二聯式發票則只會顯示前兩者。
▼以下是一個Cucumber範例,第一個例子是開立三聯式發票。稅率5%,含稅價格17000,則稅金為810,未稅價格為16190。
這個用「文字」寫成的例子,其中Given、When、Then、And開頭的每一條敘述稱為一個step(步驟)。要讓這個例子「跑起來」,必須要連結到step definition(步驟定義)程式,也就是這系列文章前幾集提到的「膠水程式」。
▼有些IDE有內建或外掛工具可以自動產生step definition程式,如果沒有也沒關係,直接跑Cucumber會看到以下錯誤訊息:
Cucumber告訴我們有1個Scenario其中包含5個Step都沒有定義,並且建議宣告長成上圖中「那個樣子」的程式碼來定義它。也就是說Cucumber把它想尋找的step definition程式長什麼樣子告訴我們,我們只要照抄即可。上述例子是Java 8的程式,step definition支援Lambda語法。
***
▼以下是Java 8的step definition程式碼,因為使用Lambda所以不需要針對每一個step單獨定義一個method,只要把全部的step definition寫成Lambda(沒有名字的函數)定義在建構函數之中即可。
Cucumber會用regular expression去對應step與step definition,例如:
Given The VAT rate is 0.05
對應到下面這條Lambda表示式:
Given("^The VAT rate is (\\d+)\\.(\\d+)$", (Integer arg1, Integer arg2)
「The VAT rate is」這幾個字在step和step definition中都一樣,0.05被Cucumber轉成 (\\d+)\\.(\\d+),\d代表「數字」,+代表「一或多」,() 稱為capture group,表示被括號括起來的部分要特別處理。至於\d前面要多加一個\表示逸出字元。最後,「The VAT rate is (\\d+)\\.(\\d+)」字串前後各有一個^和$字元稱為anchor,用來表示只比對到此的意思。舉個例子,如果忘了打$:
Given("^The VAT rate is (\\d+)\\.(\\d+)", (Integer arg1, Integer arg2)
則以上這個step definition可以對應到以下這兩個step:
Given The VAT rate is 0.05
Given The VAT rate is 0.08 in Japan
***
看到這裡發現Cucumber自動幫我們產生的Given("^The VAT rate is (\\d+)\\.(\\d+)$", (Integer arg1, Integer arg2)有一個問題,它把0.05當成兩個整數,中間隔著「.」這個字元,但我們希望0.05是double型態,怎麼辦?很簡單,自己改一下regular expression就可以了:
Given("^The VAT rate is (\\d+\\.\\d+)$", (Double arg1) -> {
System.out.println("VAT = " + arg1);
});
▼執行結果確認Cucumber有把0.05當成double傳進來。
***
剛開始看到Cucumber產生的step definition可能會被其中奇怪的符號給嚇一跳,仔細一看其實不難理解,除了\d以外,另外還有兩個常用的字元表示法:
- \w:[A-Za-z0-9_],英文字母和數字,以及底線符號。
- \s:[\t\r\n],代表空白字元。
***
友藏內心獨白:看久了就習慣了。
延伸閱讀
沒有留言:
張貼留言