上篇我們說到如何從Github上clone出一個JBehave項目,既是為了學習JBehava,也是為了熟悉下Github。
從clone下來的項目看來,基本沒什么問題,稍微捋一捋就可以運行,但是就clone下來的代碼來看,自己還是遇到一個問題(不知道是代碼問題,還是我自己的操作有問題),就是沒有辦法運行(后面會詳說)。
正如上篇所說,構建一個JBehave的應用的5大步驟:
- Write story
- Map steps to Java
- Configure Stories
- Run Stories
- View Reports
這里,我們結合clone下來的項目分別對應這五個步驟了解JBehave是如何運行的並完成測試的。
1.Write story,設定一個story,給出一個情景,使用通用語言進行表示,不管是開發或是非開發的都能看懂
本項目有兩個測試案例,一個是模擬登錄的story:
loginYahoo.story: Narrative: In order to show the yahoo function As a user I want to login yahoo Scenario: normal login Given yahoo login address by.bouncer.login.yahoo.com Then print successful
另一個是模擬瀏覽的story:
TestStroies.story: Browse Etsy.com Meta: @category browsing @color red Narrative: In order to show the browsing cart functionality As a user I want to browse in a gallery Scenario: Browsing around the site for items Given I am on localhost Then print hello world !--Examples: !--|host|hello| !--|localhost|hello world| !--|www.baidu.com|hello baidu|
2.Map steps to Java, 將上述的每個story細分成每一個step,給出Given條件,則會得到Then的結果,從而將通用語言轉換成可以通過代碼邏輯描述的問題
loginYahoo.story對應的steps類TestLogin.java:
public class TestLogin {
@Given("yahoo login address $url")
public void getHostPage(String url){
System.out.println("++++++++++++++++++++++++++++++"+url);
}
@Then("print $successful")
public void hello(String successful){
System.out.println("++++++++++++++++++++++++++++++"+successful);
}
}
TestStories.story對應的steps類TestStep.java:
public class TestStep {
@Given("I am on $host")
public void getHostPage(String host){
System.out.println("----------------------"+host);
}
@Then("print $hello")
public void hello(String hello){
System.out.println("----------------------"+hello);
}
}
3.Configure Stories 配置一些映射關系,比如如何找到並加載story文件等
public class EmbedderBase extends Embedder{
@Override
public EmbedderControls embedderControls() {
return new EmbedderControls().doIgnoreFailureInStories(true).doIgnoreFailureInView(true);
}
@Override
public Configuration configuration() {
Class<? extends EmbedderBase> embedderClass = this.getClass();
//MostUsefulConfiguration使用默認的配置
return new MostUsefulConfiguration()
//設置story文件的加載路徑
.useStoryLoader(new LoadFromClasspath(embedderClass.getClassLoader()))
//設定生成報告的相關配置
.useStoryReporterBuilder(new StoryReporterBuilder()
.withCodeLocation(CodeLocations.codeLocationFromClass(embedderClass))
.withFormats(Format.CONSOLE, Format.TXT)
.withCrossReference(new CrossReference()))
//設定相關參數的轉換
.useParameterConverters(new ParameterConverters()
.addConverters(new DateConverter(new SimpleDateFormat("yyyy-MM-dd")))) // use custom date pattern
.useStepMonitor(new SilentStepMonitor());
}
}
4.Run Stories
public class TraderStoryRunner {
@Test(groups={"test"})
public void runClasspathLoadedStoriesAsJUnit() {
// Embedder defines the configuration and candidate steps
Embedder embedder = new TestStories();
List<String> storyPaths = new StoryFinder().findPaths(CodeLocations.codeLocationFromClass(this.getClass()),"**/TestStories.story",""); // use StoryFinder to look up paths
embedder.runStoriesAsPaths(storyPaths);
}
@Test(groups={"test"})
public void runClasspathLoadedStories() {
// Embedder defines the configuration and candidate steps
Embedder embedder = new loginYahoo();
List<String> storyPaths = new StoryFinder().findPaths(CodeLocations.codeLocationFromClass(this.getClass()),"**/loginYahoo.story",""); // use StoryFinder to look up paths
embedder.runStoriesAsPaths(storyPaths);
}
}
這里可以看出,聲明了兩個類TestStories和loginYahoo。
TestStories.java
public class TestStories extends EmbedderBase {
@Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration(), new TestStep());//設定需要映射的step類
}
}
loginYahoo.java:
public class loginYahoo extends EmbedderBase {
@Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration(), new TestLogin());//設定需要映射的step類
}
}
這兩個類是一個橋梁的作用,用於設定從story到step的映射,注意這里的兩個類是繼承類EmbedderBase的,而EmbedderBase類又是Embedder的子類。
這是項目給出的測試類TraderStoryRunner,但是這里有一個問題,就是沒有找到運行的入口,點擊右鍵,除了一些maven的操作,並沒有其他可以運行的指標,比如junit。
所以通過摸索,按照自己的方法,發現首先要做的就是添加junit測試庫,這是必須的。具體步驟:
右鍵項目->Build path->Configured build path

打開對話框,選擇Libraries->Add Library->JUnit,點擊next,選擇junit4->finished。

添加完Junit后,新建一個Junit測試類

將TraderStoryRunner類的主體方法放進去,命名為Tc.java
import static org.junit.Assert.*;
import java.util.List;
import org.jbehave.core.embedder.Embedder;
import org.jbehave.core.io.CodeLocations;
import org.jbehave.core.io.StoryFinder;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.story.TestStories;
import com.story.loginYahoo;
public class Tc {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
// @Test : 表示這是一個測試用例,只有標識了改符號的函數才會被執行測試
@Test
public void runClasspathLoadedStoriesAsJUnit() {
// Embedder defines the configuration and candidate steps
Embedder embedder = new TestStories();
List<String> storyPaths = new StoryFinder().findPaths(CodeLocations.codeLocationFromClass(this.getClass()),"**/TestStories.story",""); // use StoryFinder to look up paths
embedder.runStoriesAsPaths(storyPaths);
}
@Test
public void runClasspathLoadedStories() {
// Embedder defines the configuration and candidate steps
Embedder embedder = new loginYahoo();
List<String> storyPaths = new StoryFinder().findPaths(CodeLocations.codeLocationFromClass(this.getClass()),"**/loginYahoo.story",""); // use StoryFinder to look up paths
embedder.runStoriesAsPaths(storyPaths);
}
}
至此,這個項目是可以運行起來了。
5.View Reports
點擊運行上面的Tc.java類,可以得到:
Processing system properties {}
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=false,ignoreFailureInView=false,verboseFailures=false,verboseFiltering=false,storyTimeoutInSecs=300,threads=1]
(BeforeStories)
Running story com/story/TestStories.story
Narrative:
In order to show the browsing cart functionality
As a user
I want to browse in a gallery
Browse Etsy.com
(com/story/TestStories.story)
Meta:
@category browsing
@color red
Scenario: Browsing around the site for items
----------------------localhost
Given I am on localhost
----------------------hello world
!--Examples:
!--|host|hello|
!--|localhost|hello world|
!--|www.baidu.com|hello baidu|
Then print hello world
!--Examples:
!--|host|hello|
!--|localhost|hello world|
!--|www.baidu.com|hello baidu|
(AfterStories)
Generating reports view to 'C:\Program Files (x86)\Git\Jbehave\TestBehave_v2_testng\target\jbehave' using formats '[console, txt]' and view properties '{defaultFormats=stats, decorateNonHtml=true, viewDirectory=view, decorated=ftl/jbehave-report-decorated.ftl, reports=ftl/jbehave-reports-with-totals.ftl, maps=ftl/jbehave-maps.ftl, navigator=ftl/jbehave-navigator.ftl, views=ftl/jbehave-views.ftl, nonDecorated=ftl/jbehave-report-non-decorated.ftl}'
Reports view generated with 0 stories (of which 0 pending) containing 0 scenarios (of which 0 pending)
Processing system properties {}
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=false,ignoreFailureInView=false,verboseFailures=false,verboseFiltering=false,storyTimeoutInSecs=300,threads=1]
(BeforeStories)
Running story com/story/loginYahoo.story
Narrative:
In order to show the yahoo function
As a user
I want to login yahoo
(com/story/loginYahoo.story)
Scenario: normal login
++++++++++++++++++++++++++++++by.bouncer.login.yahoo.com
Given yahoo login address by.bouncer.login.yahoo.com
++++++++++++++++++++++++++++++successful
Then print successful
(AfterStories)
Generating reports view to 'C:\Program Files (x86)\Git\Jbehave\TestBehave_v2_testng\target\jbehave' using formats '[console, txt]' and view properties '{defaultFormats=stats, decorateNonHtml=true, viewDirectory=view, decorated=ftl/jbehave-report-decorated.ftl, reports=ftl/jbehave-reports-with-totals.ftl, maps=ftl/jbehave-maps.ftl, navigator=ftl/jbehave-navigator.ftl, views=ftl/jbehave-views.ftl, nonDecorated=ftl/jbehave-report-non-decorated.ftl}'
Reports view generated with 0 stories (of which 0 pending) containing 0 scenarios (of which 0 pending)
大體的思路,是將story和step對應起來,將story中的條件、參數傳入step對應的類中,如果滿足則通過測試,得到then給出的結果,否則得不到理想的結果。
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續關注我的文章,請掃描二維碼,關注JackieZheng的微信公眾號,我會將我的文章推送給您,並和您一起分享我日常閱讀過的優質文章。
友情贊助
如果你覺得博主的文章對你那么一點小幫助,恰巧你又有想打賞博主的小沖動,那么事不宜遲,趕緊掃一掃,小額地贊助下,攢個奶粉錢,也是讓博主有動力繼續努力,寫出更好的文章^^。
1. 支付寶 2. 微信


