Cucumber 入门一
(轉(zhuǎn)自:http://www.cnblogs.com/jarodzz/archive/2012/07/02/2573014.html)
第一次看到Cucumber和BDD(Behavior Driven Development, 行為驅(qū)動(dòng)開發(fā)),是在四年前。那時(shí)才開始工作,對軟件測試工具相當(dāng)著迷。僅僅要是開源的、免費(fèi)的,我就一定要下載,安裝,試用。有的工具用途單一、好懂(如Jmeter,Watir);有的工具,則涉及到一些軟件領(lǐng)域的獨(dú)有概念,不好懂,(如STAF,Cucumber)。好懂的,我上手、試用、推廣,不亦樂乎;不好懂的,就僅僅能丟在一邊,這里面就包含Cucumber。
再次看到Cucumber,已是兩年前。我對軟件開發(fā)的理解也深了些,這一看,可真是個(gè)好東西。之后我與Cucumber間發(fā)生的故事,稍后慢慢向大家交代。這開篇的第一章,我想獻(xiàn)給如當(dāng)年的我一樣,偶然見到了Cucumber和BDD,卻不明所以將之丟在一邊的家伙們。
初聞Cucumber的人,第一件事一定是來到Cucumber的首頁,第一眼看到的一定是
非常不幸的是,這六張圖不太好懂。由于它們依照BDD的流程來編寫的。為了讓它們好懂些,我們拋開BDD,採用傳統(tǒng)的軟件開發(fā)模型(設(shè)計(jì)->編碼->測試)來看它。傳統(tǒng)流程例如以下:
圖1,這是一個(gè)被測系統(tǒng)——用ruby編寫的計(jì)算器。
為了便于大家理解,我試著改動(dòng)了一些。
| class?Calculator? ??def?push(n)??? #記數(shù) ????@args?||= [] #初始化空數(shù)組 ????@args?<< n? ??end ??def?sum()????? #返回全部數(shù)字和 ????sum = 0 ????@args.each?do?|i| ??????sum += i ????end ????@result?= sum ??end ??def?result ????@result ??end end |
?
計(jì)算器Calculator提供兩個(gè)功能: 記數(shù)push;加和sum。push將數(shù)字一一記錄在@args數(shù)組中;sum則將全部@args數(shù)組中的數(shù)字累加得和,存入@result中。寫完了被測系統(tǒng),我們來編寫測試用例。
圖2,這是為了測試上述計(jì)算器,使用Cucumber描寫敘述的測試用例。
原圖中的英文描寫敘述,被我翻譯成了中文。:
| Feature: 計(jì)算器 ??Scenario: 兩數(shù)相加 ????Given 我有一個(gè)計(jì)算器 ????And 我向計(jì)算器輸入50 ????And 我向計(jì)算器輸入70 ????When 我點(diǎn)擊累加 ????Then 我應(yīng)該看到結(jié)果120 |
?
支持中、英等自然語言,是Cucumber的特點(diǎn)之中的一個(gè)。在Cucumber的幫助文檔里,聲明它支持包含中文簡體、繁體中文、日文、韓文和英文在內(nèi)的45種語言。
注意:我并未將全部英文都翻譯成中文,而是留下了幾個(gè)keyword:
- Feature(功能)
- Scenario(情景)
- Given(給定)
- And(和)
- When(當(dāng))
- Then(則)
它們的含義與原有自己主動(dòng)化測試工具中的概念同樣,類比方下:
| Feature (功能) | test suite (測試用例集) |
| Scenario(情景) | test case (測試用例) |
| Given(給定) | setup(創(chuàng)建測試所需環(huán)境) |
| When(當(dāng)) | test(觸發(fā)被測事件) |
| Then(則) | assert(斷言,驗(yàn)證結(jié)果) |
Cucumber放棄了原有的keyword,而選擇了左邊五種,僅僅是為了更加流暢地支持自然語言。使用Cucumber的keyword,創(chuàng)建了測試用例,接下來,要怎樣使用Cucumber來執(zhí)行它呢?
圖3,這是執(zhí)行Cucumber時(shí)的畫面。
在一臺安裝好Cucumber的機(jī)器上,執(zhí)行上述測試用例,便能夠看到下列輸出:
| Feature: 計(jì)算器 ??Scenario: 兩數(shù)相加??? # features/calculator.feature:3 ????Given 我有一個(gè)計(jì)算器?? # features/calculator.feature:4 ????And 我向計(jì)算器輸入50???# features/calculator.feature:5 ????And 我向計(jì)算器輸入70???# features/calculator.feature:6 ????When 我點(diǎn)擊累加????? # features/calculator.feature:7 ????Then 我應(yīng)該看到結(jié)果120?# features/calculator.feature:8 1?scenario (1?undefined) 5?steps (5?undefined) 0m0.005s You can implement step definitions for?undefined steps with these snippets: Given /^我有一個(gè)計(jì)算器$/ do ??pending # express the regexp above with the code you wish you had end Given /^我向計(jì)算器輸入(\d+)$/ do?|arg1| ??pending # express the regexp above with the code you wish you had end When /^我點(diǎn)擊累加$/ do ??pending # express the regexp above with the code you wish you had end Then /^我應(yīng)該看到結(jié)果(\d+)$/ do?|arg1| ??pending # express the regexp above with the code you wish you had end |
?
Cucumber首先輸出的是測試用例的描寫敘述,然后3行總結(jié)性地輸出:本功能(Feature)有1個(gè)情景(1 scenario);5個(gè)步驟(5 steps),所有5個(gè)步驟均沒有定義(undefined);執(zhí)行耗時(shí)0.005秒。這里出現(xiàn)了兩個(gè)新名詞:步驟(steps)和步驟定義(step definitions)。在Cucumber中,以keywordGiven, And, When, Then開頭的每一行,為一個(gè)步驟。在兩數(shù)相加的情景中,一共同擁有5行。因此,結(jié)果顯示:5個(gè)步驟。
怎樣定義一個(gè)步驟,在Cucumber的執(zhí)行結(jié)果中也給出了具體的辦法。在3行總結(jié)性輸出后,緊接著便是:You can implement…即:你能夠使用以下的代碼段實(shí)現(xiàn)步驟定義,然后是4個(gè)小的代碼段。這些代碼段,便是Cucumber按照情境中我們使用的5個(gè)步驟,幫助我們生成的步驟定義框架。每一個(gè)框架都將內(nèi)容部分空白出來,等待填充。以下,我們來進(jìn)行步驟定義。
圖4, 這是一個(gè)步驟定義的代碼示范。
我們按照圖2的樣子,向中文步驟中填入代碼,例如以下:
| Given /^我有一個(gè)計(jì)算器$/ do ??@c?= Calculator.new end Given /^我向計(jì)算器輸入(\d+)$/ do?|num| ??@c.push(num.to_i) end When /^我點(diǎn)擊累加$/ do ??@c.sum end Then /^我應(yīng)該看到結(jié)果(\d+)$/ do?|result| ??@c.result.should == result.to_i end |
?
步驟定義的過程,就是向代碼段——步驟定義框架——中填入代碼的過程,即:用代碼來描寫敘述你期望的,該步驟應(yīng)該運(yùn)行的動(dòng)作。完整的步驟定義是一個(gè)函數(shù),它:
- 以正則表達(dá)式作為函數(shù)名
- 匹配值作為參數(shù)
- 以測試人員輸入的代碼作為內(nèi)容
由于有了正則表達(dá)式的匹配,5個(gè)步驟僅須要4個(gè)步驟定義。“我向計(jì)算器輸入50、70”兩個(gè)步驟,都能夠用“我向計(jì)算器輸入(\d+)”一個(gè)正則表達(dá)式來描寫敘述。匹配值被自己主動(dòng)提取出來作為參數(shù),傳入代碼。注意:全部匹配值,即參數(shù),都是以字符串的形式傳遞,因此,我增加了num.to_i 與 result.to_i,將得到的字符串轉(zhuǎn)為整形。步驟定義完畢,再次運(yùn)行Cucumber。屏幕將會(huì)顯示一片綠色。
圖5,它是一個(gè)運(yùn)行Cucumber測試用例,并成功通過的畫面。
步驟定義完畢后,再次執(zhí)行Cucumber。Cucumber會(huì)找到步驟定義,并依照其代碼去執(zhí)行。結(jié)果例如以下:
| Feature: 加法 ??Scenario: 兩數(shù)相加??? # features/calculator.feature:3 ????Given 我有一個(gè)計(jì)算器?? # features/step_definitions/a.rb:2 ????And 我向計(jì)算器輸入50???# features/step_definitions/a.rb:6 ????And 我向計(jì)算器輸入70???# features/step_definitions/a.rb:6 ????When 我點(diǎn)擊累加????? # features/step_definitions/a.rb:10 ????Then 我應(yīng)該看到結(jié)果120?# features/step_definitions/a.rb:14 1?scenario (1?passed) 5?steps (5?passed) 0m0.003s |
?
步驟定義被我保存在目錄step_definitions下的a.rb其中。步驟定義所在文件與起始行數(shù),被打印在每一個(gè)步驟結(jié)尾,以方便查找和改動(dòng)。最后,Cucumber總結(jié)性地輸出執(zhí)行結(jié)果:1個(gè)情景,5個(gè)步驟,所有通過。
圖6, 這是一個(gè)運(yùn)行Cucumber測試用例,但失敗的畫面。
為了讓這個(gè)已經(jīng)十分簡單的計(jì)算器產(chǎn)生bug,我僅僅好將它改錯(cuò)為:
| class?Calculator ??def?sum() ????sum = 0 ????@args.each?do?|n| ??????sum = n??? #此處原為:sum += n ????end ????@result?= sum ??end end |
?
再次執(zhí)行Cucumber,結(jié)果為:
?| Feature: 加法 ??Scenario: 兩數(shù)相加??? # features/calculator.feature:3 ????Given 我有一個(gè)計(jì)算器?? # features/step_definitions/a.rb:2 ????And 我向計(jì)算器輸入50???# features/step_definitions/a.rb:6 ????And 我向計(jì)算器輸入70???# features/step_definitions/a.rb:6 ????When 我點(diǎn)擊累加????? # features/step_definitions/a.rb:10 ????Then 我應(yīng)該看到結(jié)果120?# features/step_definitions/a.rb:14 ??????expected: 120 ???????????got: 70?(using ==) (RSpec::Expectations::ExpectationNotMetError) ??????./features/step_definitions/a.rb:15:in?`/^我應(yīng)該看到結(jié)果(\d+)$/' ??????features/calculator.feature:8:in?`Then 我應(yīng)該看到結(jié)果120' Failing Scenarios: cucumber features/calculator.feature:3?# Scenario: 兩數(shù)相加 1?scenario (1?failed) 5?steps (1?failed, 4?passed) 0m0.004s |
?
失敗的步驟是用紅色標(biāo)示出來的。在最后一個(gè)步驟中,Cucumber期待的結(jié)果為120,但得到的是70。注意:失敗的情景列表(Failing Scenarios)里列出的是:“兩數(shù)相加”這個(gè)情景所在的文件與起始行數(shù)。這是由于一個(gè)功能文件內(nèi),可能含有多個(gè)情景,這樣的輸出能夠便于找到出錯(cuò)的情景。
接下來的總結(jié)性結(jié)果為:1個(gè)情景失敗(1 failed),5個(gè)步驟中,4個(gè)通過,1個(gè)失敗。
作為自己主動(dòng)化測試工具的Cucumber,就介紹到這里。
在繼續(xù)之前,我們先回想一下本章內(nèi)容。
回想:
- Cucumber是一個(gè)自己主動(dòng)化測試工具
- 它提供了自然語言的支持,我們能夠用自然語言描寫敘述、并運(yùn)行測試用例
- 它提供了自然語言與代碼的銜接,通過步驟與步驟定義
- 它提供了自然語言對代碼的調(diào)用,當(dāng)步驟定義結(jié)束后,執(zhí)行Cucumber,它會(huì)自己主動(dòng)調(diào)用步驟定義內(nèi)的代碼執(zhí)行
- 它提供了良好的斷言(assert)機(jī)制。當(dāng)運(yùn)行失敗時(shí),我們能夠看到完畢的測試用例,以及明白的失敗原因。
轉(zhuǎn)載于:https://www.cnblogs.com/bhlsheji/p/4024431.html
總結(jié)
以上是生活随笔為你收集整理的Cucumber 入门一的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【树的直径】 POJ 1985 Cow
- 下一篇: LeetCode-Populating