2016-03-14 52 views
1

我正在使用JBehave編寫BDD集成測試。
問題:JBehave清除對象(實例變量)的狀態,同時執行各個步驟
代碼: StepDefinition:JBehave如何在步驟之間保持對象狀態

public class StepDefs { 

    private String str; 

    @Given("step represents a precondition to an $event") 
    public void given(String event){ 
     str=event; 
     System.out.println("Given: "+str); 
    } 

    @When("step represents the occurrence of the event") 
    public void when() { 
     System.out.println("When: "+str); 
    } 

    @Then("step represents the outcome of the event") 
    public void then() { 

    } 
} 

故事:

Sample story 

Narrative: 
In order to communicate effectively to the business some functionality 
As a development team 
I want to use Behaviour-Driven Development 

Scenario: A scenario is a collection of executable steps of different type 
Given step represents a precondition to an event 
When step represents the occurrence of the event 
Then step represents the outcome of the event 

JBehaveJUnitTestRunner:

@RunWith(JUnitReportingRunner.class) 
public class JBehaveTestsRunner extends JUnitStories { 

    private CrossReference xref = new CrossReference(); 

    public JBehaveTestsRunner() { 
     configuredEmbedder().embedderControls().doGenerateViewAfterStories(true).doIgnoreFailureInStories(true) 
       .doIgnoreFailureInView(true).doVerboseFailures(true);// .useThreads(1); 
    } 

    @Override 
    public Configuration configuration() { 
     Properties viewResources = new Properties(); 
     viewResources.put("decorateNonHtml", "true"); 
     return new MostUsefulConfiguration().useStoryLoader(new LoadFromClasspath(this.getClass().getClassLoader())) 
       .useStoryReporterBuilder(
         new StoryReporterBuilder().withFormats(Format.HTML, Format.CONSOLE, Format.STATS) 
           .withViewResources(viewResources).withFailureTrace(true).withFailureTraceCompression(false) 
           .withCrossReference(xref)); 
    } 

    @Override 
    public InjectableStepsFactory stepsFactory() { 
     return new ScanningStepsFactory(configuration(), "stepdefs"); 
    } 

    @Override 
    public List<String> storyPaths() { 
     StoryFinder finder = new StoryFinder(); 
     return finder.findPaths(CodeLocations.codeLocationFromClass(getClass()), Arrays.asList("**/Simple.story"), null); 
    } 
} 

實際輸出:

Processing system properties {} 
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=true,ignoreFailureInView=true,verboseFailures=true,verboseFiltering=false,storyTimeouts=300,threads=1,failOnStoryTimeout=false] 

(BeforeStories) 

Running story stories/Simple.story 
Sample story 
(stories/Simple.story) 
Narrative: 
In order to communicate effectively to the business some functionality 
As a development team 
I want to use Behaviour-Driven Development 
Scenario: A scenario is a collection of executable steps of different type 
**Given: event** 
Given step represents a precondition to an event 
**When: null** 
When step represents the occurrence of the event 
Then step represents the outcome of the event 



(AfterStories) 

Generating reports view to 'C:\WORKING\lunaworkspace\pkeautomation\target\jbehave' using formats '[html, console, stats, junitscenarioreporter]' and view properties '{decorateNonHtml=true}' 
log4j:WARN No appenders could be found for logger (freemarker.cache). 
log4j:WARN Please initialize the log4j system properly. 
Reports view generated with 3 stories (of which 1 pending) containing 2 scenarios (of which 1 pending) 

可以看出在輸出:在給定的步驟我接受對此我它初始化爲實例變量「STR」字符串參數,同時進行打印的值到控制檯我可以成功地看到它。但是,當第二步即執行步驟時,我得到空值作爲實例變量「str」的值。如何讓JBehave在執行各個步驟後不清除對象的狀態?

+0

的可能的複製[JBehave保持整個給定的步驟數據/時/然後在一個場景(http://stackoverflow.com/questions/9389845/jbehave-maintain-data-across-steps-given-when-then-during-a-scenario) - 儘管我只是看了看,並沒有真正解釋如何做到這一點,所以收回近距離投票。鏈接到答案而不把這些答案的實際內容放下來是不好的,人們! – Lunivore

回答

1

對於任何人尋找這個問題的答案,我確實通過從JBehave谷歌組社區的幫助找到適當的解決方案。該解決方案非常簡單,而不是使用ScanningStepFactory使用InstanceStepsFactory並且應該保持對象的狀態。鏈接到討論:Google Group discussion

片段的人來這裏回答:

package runner; 

import java.util.Arrays; 
import java.util.List; 
import java.util.Properties; 

import org.jbehave.core.configuration.Configuration; 
import org.jbehave.core.configuration.MostUsefulConfiguration; 
import org.jbehave.core.io.CodeLocations; 
import org.jbehave.core.io.LoadFromClasspath; 
import org.jbehave.core.io.StoryFinder; 
import org.jbehave.core.junit.JUnitStories; 
import org.jbehave.core.reporters.CrossReference; 
import org.jbehave.core.reporters.Format; 
import org.jbehave.core.reporters.StoryReporterBuilder; 
//import org.jbehave.core.steps.CandidateSteps; 
import org.jbehave.core.steps.InjectableStepsFactory; 
import org.jbehave.core.steps.InstanceStepsFactory; 
//import org.jbehave.core.steps.ScanningStepsFactory; 
import org.junit.runner.RunWith; 

import de.codecentric.jbehave.junit.monitoring.JUnitReportingRunner; 
import stepdefs.StepDefs; 
//import stepdefs.BarStep; 
//import stepdefs.FooStep; 

@RunWith(JUnitReportingRunner.class) 
public class JBehaveTestsRunner extends JUnitStories { 

    private CrossReference xref = new CrossReference(); 

    public JBehaveTestsRunner() { 
     configuredEmbedder().embedderControls().doGenerateViewAfterStories(true).doIgnoreFailureInStories(true) 
       .doIgnoreFailureInView(true).doVerboseFailures(true);// .useThreads(1); 
    } 

    @Override 
    public Configuration configuration() { 
     Properties viewResources = new Properties(); 
     viewResources.put("decorateNonHtml", "true"); 
     return new MostUsefulConfiguration().useStoryLoader(new LoadFromClasspath(this.getClass().getClassLoader())) 
       .useStoryReporterBuilder(new StoryReporterBuilder() 
         .withFormats(Format.HTML, Format.CONSOLE, Format.STATS).withViewResources(viewResources) 
         .withFailureTrace(true).withFailureTraceCompression(false).withCrossReference(xref)); 
    } 

    /*@Override 
    public List<CandidateSteps> candidateSteps() { 
     return new InstanceStepsFactory(configuration(), new FooStep(), new BarStep(), new StepDefs()) 
       .createCandidateSteps(); 
    }*/ 

    @Override 
    public InjectableStepsFactory stepsFactory() { 
     return new InstanceStepsFactory(configuration(), new StepDefs()); 
     // return new ScanningStepsFactory(configuration(), "stepdefinitions"); 
    } 

    @Override 
    public List<String> storyPaths() { 
     StoryFinder finder = new StoryFinder(); 
     return finder.findPaths(CodeLocations.codeLocationFromClass(getClass()), Arrays.asList("**/Sample.story"), 
       null); 
    } 
} 
+0

你能分享一個代碼嗎?或者給一些使用InstanceStepsFactory的鏈接? – Anton

+0

@Anton根據要求添加示例代碼片段。 –

0

自從我使用JBehave以來已經有一段時間了。可能是您正在爲每個stepsFactory()呼叫創建一個新的ScanningStepsFactory。嘗試在構造函數中創建其中的一個,然後將該實例傳回,以便每次調用都不會創建一個新實例。

,如果失敗,嘗試使用InstanceStepsFactory作爲例子here

public abstract class NoughtsAndCrossesStory extends JUnitStory { 

    public NoughtsAndCrossesStory() { 
     Configuration configuration = new MostUsefulConfiguration() 
      .useStoryPathResolver(new UnderscoredCamelCaseResolver("")) 
      .useStoryReporterBuilder(new StoryReporterBuilder() 
       .withCodeLocation(CodeLocations.codeLocationFromClass(this.getClass())) 
       .withDefaultFormats() 
       .withFormats(CONSOLE, TXT) 
       .withFailureTrace(true)); 
     useConfiguration(configuration); 
     WindowControl windowControl = new WindowControl(); 
     addSteps(new InstanceStepsFactory(configuration,new GridSteps(windowControl), new BeforeAndAfterSteps(windowControl)).createCandidateSteps()); 
    } 

} 

你需要創建某種在其中容納你的字符串持久存儲庫的對象(在上面的例子中, windowControl仍然存在)。

public class BeforeAndAfterSteps extends Steps { 

    private final WindowControl windowControl; 

    public BeforeAndAfterSteps(WindowControl windowControl) { 
     this.windowControl = windowControl; 
    } 

    @BeforeScenario 
    public void beforeScenarios() throws Exception { 
     windowControl.reset(); 
    } 

    @AfterScenario 
    public void afterScenarios() throws Exception { 
     windowControl.destroy(); 
    } 
} 

這使您不僅可以跨步驟,而且可以在場景之間保持狀態。請注意,這通常被認爲是不好的做法;我在這裏使用這個來確保狀態是而不是在場景之間持續存在,但理論上你可以使用它來在運行測試套件之前初始化默認數據。

+0

已創建ScanningStepsFactory的單例isntance,但無效。另一種方法對於這樣一個簡單的需求將會是太多的編碼(因爲會有很多我想要維護的實例變量)。也許JBehave不適合我,但現在我會接受你的回答,如果第二種方法是JBehave用戶需要做的。謝謝 –

+0

如果你有很多實例變量,可以考慮創建一個「世界」類並將所有實例存儲在那裏。它會給你完全的控制權,允許你重置它等。 - 你可以在@BeforeScenario步驟中創建一個新的控件,並確保它始終保持新鮮。另外考慮問JBehave用戶列表,因爲我對JBehave的知識是* old *(例如):http://jbehave.org/mailing-lists.html – Lunivore

+0

感謝您的幫助。我確實在郵件列表中詢問過,但看起來你上面所說的是做這件事的唯一方法。我用黃瓜JVM來實現BDD,但是想試試如果JBehave是一個更好的選擇或者不是。似乎我現在需要堅持到黃瓜。您提供的解決方案是太多不必要的編碼,因爲它在黃瓜中隨時可用,而無需執行任何操作。再次感謝您的幫助。非常感謝:) –

相關問題