cucumber java從入門到精通(3)簡單實現及斷言


cucumber java從入門到精通(3)簡單實現及斷言

上一節里我們定義了step的java代碼實現文件,step就是測試步驟及斷言的集合,我們先定義出來,以后可以驅動開發以及在持續集成時重用。

這一節我們將近距離細觀一下所謂的step java實現。以下面的代碼片段為例:

<code class="sourceCode java hljs" style="margin:0px; display:block; overflow-x:auto; padding:5px!important; line-height:1.5!important; font-family:'Courier New',sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important; background:rgb(255,255,255)"><span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span> <span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-class" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">class</span></span></span><span class="hljs-class" style="margin:0px; padding:0px; line-height:1.5"> <span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">TodoStep</span> </span>{ <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">//1                                                                             </span></span>
@假設(<span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">"^我的任務清單里有(</span></span><span class="ch" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">\\</span></span><span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">d+)個任務$"</span></span>) <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">//2 </span></span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">void</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">iHaveSomeTasks</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5">(</span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"> totalTasks)</span> </span><span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throws</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> Throwable </span>{ <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">//3 </span></span>
<span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// Write code here that turns the phrase above into concrete actions </span></span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throw</span></span> <span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">new</span></span> <span class="fu" style="margin:0px; padding:0px; line-height:1.5">PendingException</span>(); <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">//4 </span></span>
}
}</code>
  • //1 定義了public class,這沒什么好說的;
  • //2 假設注解,這個注解表明下面的方法對應的也就是feature文件中我的任務清單里有xxxx個任務這個步驟;
  • //3 定義了具體實現feature文件步驟的方法,並從feature定義中取得傳入參數,也就是xxxx個任務的具體值;
  • //4 拋出Pending異常,表明該步驟暫未實現,但來日方長,也許有天可以實現;

cucmber執行順序

如果你對上面的代碼尚有疑問,那么是時候看一下cucumber的執行順序了,以下面代碼片段為例:

<code class="sourceCode java hljs" style="margin:0px; display:block; overflow-x:auto; padding:5px!important; line-height:1.5!important; font-family:'Courier New',sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important; background:rgb(255,255,255)"># feature
假設 我的任務清單里有<span class="dv" style="margin:0px; padding:0px; line-height:1.5">3</span>個任務 <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// 1</span></span>
當 我完成<span class="dv" style="margin:0px; padding:0px; line-height:1.5">1</span>件任務之后 <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// 2</span></span>
那么 我還剩下<span class="dv" style="margin:0px; padding:0px; line-height:1.5">2</span>件未完成的任務 <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">//3</span></span>

# step
@假設(<span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">"^我的任務清單里有(</span></span><span class="ch" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">\\</span></span><span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">d+)個任務$"</span></span>) <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">//4 </span></span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">void</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">iHaveSomeTasks</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5">(</span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"> totalTasks)</span> </span><span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throws</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> Throwable </span>{ <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">//5 </span></span>
<span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// Write code here that turns the phrase above into concrete actions </span></span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throw</span></span> <span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">new</span></span> <span class="fu" style="margin:0px; padding:0px; line-height:1.5">PendingException</span>();
}

@當(<span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">"^我完成(</span></span><span class="ch" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">\\</span></span><span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">d+)件任務之后$"</span></span>) <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">//6 </span></span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">void</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">iFinishSomeTasks</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5">(</span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"> finishedTasks)</span> </span><span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throws</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> Throwable </span>{ <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">//7 </span></span>
<span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// Write code here that turns the phrase above into concrete actions </span></span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throw</span></span> <span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">new</span></span> <span class="fu" style="margin:0px; padding:0px; line-height:1.5">PendingException</span>();
}

@那么(<span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">"^我還剩下(</span></span><span class="ch" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">\\</span></span><span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">d+)件未完成的任務$"</span></span>) <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">//8 </span></span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">void</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">iLeftSomeTasks</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5">(</span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"> leftTasks)</span> </span><span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throws</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> Throwable </span>{ <span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">//9 </span></span>
<span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// Write code here that turns the phrase above into concrete actions </span></span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throw</span></span> <span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">new</span></span> <span class="fu" style="margin:0px; padding:0px; line-height:1.5">PendingException</span>();
} </code>
  • 當我們運行了run命令后(還記得上一節的run嗎?其實就是執行了cucumber.api.cli.Main。),cucumber會去找feature文件,然后執行第1條feature語句,也就是//1
  • 執行//1的時候,cucumber會去找對應的step定義文件,尋尋覓覓的過程中,cucumber發現了對應的注解,也就是//4
  • //4告訴cucumber,下面緊接着定義的那個方法就是該feature對應的代碼實現,於是cucumber再去執行//5
  • 在執行//5的時候,cucumber將3作為totalTasks這個參數傳給//5
  • cucumber執行//5方法體中的內容並收到pending異常,於是該feature執行結束,轉去執行下1條feature

小練習:你能自己說明//2以及//3的執行順序嗎

漸進重構之假裝實現

回憶一下我們的測試目標,我們要測試一個todo list,第1步也就是在測試背景或者叫做前置條件里,我們是這樣描述的

假設 我的任務清單里有3個任務 // 1

這時候不妨假設我們有個TodoList類,該類有個getTotalTaskCount()方法返回任務清單中一共有多少條任務。基於這個想法,我們重構一下TodoStep.java文件

<code class="sourceCode java hljs" style="margin:0px; display:block; overflow-x:auto; padding:5px!important; line-height:1.5!important; font-family:'Courier New',sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important; background:rgb(255,255,255)">
@假設(<span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">"^我的任務清單里有(</span></span><span class="ch" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">\\</span></span><span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">d+)個任務$"</span></span>)
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">void</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">iHaveSomeTasks</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5">(</span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"> totalTasks)</span> </span><span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throws</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> Throwable </span>{
<span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// totalTasks == 3</span></span>
TodoList todo = <span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">new</span></span> <span class="fu" style="margin:0px; padding:0px; line-height:1.5">TodoList</span>();
<span class="fu" style="margin:0px; padding:0px; line-height:1.5">assertEquals</span>(todo.<span class="fu" style="margin:0px; padding:0px; line-height:1.5">getTotalTaskCount</span>(), totalTasks);
} </code>

在這里要說明的是注解中的(\d)表示獲取feature定義中的數字字符並把該數字(int)作為totalTasks參數傳入iHaveSomeTasks方法。因此totalTaks應該等於3。另外assertEquals是jUnit的斷言方法

執行一下compile && run,得到下面的結果

step_definitions\TodoStep.java:11: 錯誤: 找不到符號
TodoList todo = new TodoList()
;
^
符號: 類 TodoList
位置: 類 TodoStep
step_definitions\TodoStep.java:11: 錯誤: 找不到符號
TodoList todo = new TodoList()
;
^
符號: 類 TodoList
位置: 類 TodoStep
2 個錯誤

我們無法編譯,因為TodoList這個類並沒有定義。

下面我們定義一下TodoList類。在implementation文件夾中新建1個名為TodoList.java的文件,該文件的實現是

<code class="sourceCode java hljs" style="margin:0px; display:block; overflow-x:auto; padding:5px!important; line-height:1.5!important; font-family:'Courier New',sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important; background:rgb(255,255,255)"><span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// TodoList.java</span></span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">package</span> implementation;</span>

<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span> <span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-class" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">class</span></span></span><span class="hljs-class" style="margin:0px; padding:0px; line-height:1.5"> <span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">TodoList</span> </span>{
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">getTotalTaskCount</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5">()</span> </span>{
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">return</span></span> <span class="dv" style="margin:0px; padding:0px; line-height:1.5">3</span>;
}
}</code>

下面在TodoStep.java中導入TodoList類

<code class="sourceCode java hljs" style="margin:0px; display:block; overflow-x:auto; padding:5px!important; line-height:1.5!important; font-family:'Courier New',sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important; background:rgb(255,255,255)"><span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// TodoStep.java</span></span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">import</span> implementation.TodoList;</span></code>

修改一下compile文件,因為這次我們需要TodoList.java文件,修改完成的版本應該是這樣的

# compile
javac -cp "./jars/*;." step_definitions\TodoStep.java implementation\TodoList.java
# linux && unix
javac -cp "./jars/*:." step_definitions\TodoStep.java implementation\TodoList.java

然后運行compile && run,得到下面的結果

#language: zh-CN
功能: 任務管理

場景: 完成1件任務 # todo.feature:5
假設我的任務清單里有3個任務 # TodoStep.iHaveSomeTasks(int)
當我完成1件任務之后 # TodoStep.iFinishSomeTasks(int)
cucumber.api.PendingException: TODO: implement me
at step_definitions.TodoStep.iFinishSomeTasks(TodoStep.java:19)
at ?.當我完成1件任務之后(todo.feature:7)

那么我還剩下2件未完成的任務 # TodoStep.iLeftSomeTasks(int)

1 Scenarios (1 pending)
3 Steps (1 skipped, 1 pending, 1 passed)
0m0.128s

cucumber.api.PendingException: TODO: implement me
at step_definitions.TodoStep.iFinishSomeTasks(TodoStep.java:19)
at ?.當我完成1件任務之后(todo.feature:7)

我們看到有1個step pass了,那就是我們剛定義前置條件step,所以到現在為止我們干的不錯!我們有了feature文件,該文件描述了需求和測試用例,我們完成了測試step中的前置條件,並且我們實現了1個真正的TodoList類,盡管這個類目前還是嗷嗷待哺,不過當我們實現更多的step之后,TodoList類的功能會進一步完善,直到滿足用戶需求。實際上我們現在做的就是BDD,用測試去驅動開發。

可能有的同學會對此不屑一顧,TodoList類到目前為止只是自欺欺人的實現了1個返回int型數字3的方法,離我們所要的任務清單還相差十萬八千里。其實不用擔心這個,我們的TodoList類沒有實現具體的功能是因為我們實現的測試步驟還不夠多,我們接收到的需求還只是那么一點點,當我們實現更多步驟之后,TodoList自然會羽翼豐滿。這就是所謂的最小實現原則。

漸進重構,重構剩下的2個步驟

下面我們重構剩下的2個步驟。

我們先假設TodoList有1個finishTask方法,每次調用這個方法就會完成n個任務,n從參數傳入。於是剩余的任務就會減去n。
我們再假設TodoList有1個getRestTasksCount方法,調用這個方法可以獲取剩下的task的數量。
重構完成以后,我們的代碼如下所示

<code class="sourceCode java hljs" style="margin:0px; display:block; overflow-x:auto; padding:5px!important; line-height:1.5!important; font-family:'Courier New',sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important; background:rgb(255,255,255)"><span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">package</span> step_definitions;</span>

<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">import</span> cucumber.api.java.zh_cn.*;</span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">import</span> cucumber.api.PendingException;</span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">import</span> <span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">static</span> org.junit.Assert.*;</span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">import</span> implementation.TodoList;</span>

<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span> <span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-class" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">class</span></span></span><span class="hljs-class" style="margin:0px; padding:0px; line-height:1.5"> <span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">TodoStep</span> </span>{
TodoList todo;

@假設(<span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">"^我的任務清單里有(</span></span><span class="ch" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">\\</span></span><span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">d+)個任務$"</span></span>)
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">void</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">iHaveSomeTasks</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5">(</span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"> totalTasks)</span> </span><span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throws</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> Throwable </span>{
<span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// Write code here that turns the phrase above into concrete actions </span></span>
todo = <span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">new</span></span> <span class="fu" style="margin:0px; padding:0px; line-height:1.5">TodoList</span>();
<span class="fu" style="margin:0px; padding:0px; line-height:1.5">assertEquals</span>(todo.<span class="fu" style="margin:0px; padding:0px; line-height:1.5">getTotalTaskCount</span>(), totalTasks);
}

@當(<span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">"^我完成(</span></span><span class="ch" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">\\</span></span><span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">d+)件任務之后$"</span></span>)
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">void</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">iFinishSomeTasks</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5">(</span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"> finishedTasks)</span> </span><span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throws</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> Throwable </span>{
<span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// Write code here that turns the phrase above into concrete actions </span></span>
todo.<span class="fu" style="margin:0px; padding:0px; line-height:1.5">finisheTask</span>(finishedTasks);
}

@那么(<span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">"^我還剩下(</span></span><span class="ch" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">\\</span></span><span class="st" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-string" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">d+)件未完成的任務$"</span></span>)
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">void</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">iLeftSomeTasks</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5">(</span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"> leftTasks)</span> </span><span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">throws</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> Throwable </span>{
<span class="co" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-comment" style="color:green;margin:0px; padding:0px; line-height:1.5">// Write code here that turns the phrase above into concrete actions </span></span>
<span class="fu" style="margin:0px; padding:0px; line-height:1.5">assertEquals</span>(todo.<span class="fu" style="margin:0px; padding:0px; line-height:1.5">getRestTasksCount</span>(), leftTasks);
}
} </code>

編譯一下,不出意外的失敗了,沒關系,我們再去重構TodoList.java文件。

我們先實現finishedTask方法,這個方法的方法體是空,表示什么都不做;
然后實現getRestTasksCount方法,這個方法簡單的返回2就好;

<code class="sourceCode java hljs" style="margin:0px; display:block; overflow-x:auto; padding:5px!important; line-height:1.5!important; font-family:'Courier New',sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important; background:rgb(255,255,255)">#TodoList.<span class="fu" style="margin:0px; padding:0px; line-height:1.5">java</span>
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">package</span> implementation;</span>

<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span> <span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-class" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">class</span></span></span><span class="hljs-class" style="margin:0px; padding:0px; line-height:1.5"> <span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">TodoList</span> </span>{
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">getTotalTaskCount</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5">()</span> </span>{
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">return</span></span> <span class="dv" style="margin:0px; padding:0px; line-height:1.5">3</span>;
}

<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">void</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">finishTask</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5">(</span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5"> count)</span> </span>{

}

<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">public</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="dt" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">int</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"> </span><span class="fu" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-title" style="color:#a31515;margin:0px; padding:0px; line-height:1.5">getRestTasksCount</span></span></span><span class="hljs-function" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-params" style="margin:0px; padding:0px; line-height:1.5">()</span> </span>{
<span class="kw" style="margin:0px; padding:0px; line-height:1.5"><span class="hljs-keyword" style="color:#00ff;margin:0px; padding:0px; line-height:1.5">return</span></span> <span class="dv" style="margin:0px; padding:0px; line-height:1.5">2</span>;
}
}</code>

再次運行compile && run

可以看到,我們的step全部運行通過了

#language: zh-CN                                                      
功能: 任務管理

場景: 完成1件任務 # todo.feature:5
假設我的任務清單里有3個任務 # TodoStep.iHaveSomeTasks(int)
當我完成1件任務之后 # TodoStep.iFinishSomeTasks(int)
那么我還剩下2件未完成的任務 # TodoStep.iLeftSomeTasks(int)

1 Scenarios (1 passed)
3 Steps (3 passed)
0m0.132s

總結

從這一節可以看到,我們的cucumber BDD行為驅動開發的流程是這樣的:

  1. Describe behaviour in plain text
  2. Write a step definition in Java
  3. Run and watch it fail
  4. Write code to make the step pass
  5. Run again and see the step pass
  6. Repeat 2-5 until green like a cuke

小練習:翻譯上面的6句話,弄清楚具體的意思。對照教程,請指出每一步與教程中所對應的代碼

我們簡單實現了TodoList類,目前的TodoList類是滿足我們的feature的需求的。下一節我們將增加更多的測試數據,以便完善TodoList類。



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com