2016-03-14 56 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是一个更好的选择或者不是。似乎我现在需要坚持到黄瓜。您提供的解决方案是太多不必要的编码,因为它在黄瓜中随时可用,而无需执行任何操作。再次感谢您的帮助。非常感谢:) –

相关问题