Title: [1561] trunk/core/jbehave-core/src/main/java/org/jbehave/scenario: JBEHAVE-239: Added @BeforeStory/@AfterStory annotations.

Diff

Added: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/BeforeAfterSteps.java (0 => 1561)

--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/BeforeAfterSteps.java	                        (rev 0)
+++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/BeforeAfterSteps.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -0,0 +1,33 @@
+package org.jbehave.examples.trader;
+
+import org.jbehave.scenario.annotations.AfterScenario;
+import org.jbehave.scenario.annotations.AfterStory;
+import org.jbehave.scenario.annotations.BeforeScenario;
+import org.jbehave.scenario.annotations.BeforeStory;
+
+/**
+ * Steps executed before and after each story and scenario
+ */
+public class BeforeAfterSteps {
+
+    @BeforeStory
+    public void beforeStory() {
+        System.out.println("Before Story ...");
+    }
+
+    @AfterStory
+    public void afterStory() {
+        System.out.println("After Story ...");
+    }
+    
+    @BeforeScenario
+    public void beforeScenario() {
+        System.out.println("Before Scenario ...");
+    }
+
+    @AfterScenario
+    public void afterScenario() {
+        System.out.println("After Scenario ...");
+    }
+    
+}

Modified: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderScenario.java (1560 => 1561)

--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderScenario.java	2010-02-07 18:44:35 UTC (rev 1560)
+++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderScenario.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -64,7 +64,7 @@
     }
 
     protected CandidateSteps[] createSteps(StepsConfiguration configuration) {
-        return new StepsFactory(configuration).createCandidateSteps(new TraderSteps(new TradingService()));
+        return new StepsFactory(configuration).createCandidateSteps(new TraderSteps(new TradingService()), new BeforeAfterSteps());
     }
 
     private TraderPersister mockTradePersister() {

Modified: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/PicoTraderScenario.java (1560 => 1561)

--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/PicoTraderScenario.java	2010-02-07 18:44:35 UTC (rev 1560)
+++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/PicoTraderScenario.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -1,5 +1,6 @@
 package org.jbehave.examples.trader.pico;
 
+import org.jbehave.examples.trader.BeforeAfterSteps;
 import org.jbehave.examples.trader.TraderScenario;
 import org.jbehave.examples.trader.TraderSteps;
 import org.jbehave.examples.trader.service.TradingService;
@@ -30,6 +31,7 @@
         MutablePicoContainer parent = new DefaultPicoContainer(new Caching().wrap(new ConstructorInjection()));
         parent.as(Characteristics.USE_NAMES).addComponent(TradingService.class);
         parent.as(Characteristics.USE_NAMES).addComponent(TraderSteps.class);
+        parent.as(Characteristics.USE_NAMES).addComponent(BeforeAfterSteps.class);
         return parent;
     }
     

Modified: trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/ScenarioRunnerBehaviour.java (1560 => 1561)

--- trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/ScenarioRunnerBehaviour.java	2010-02-07 18:44:35 UTC (rev 1560)
+++ trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/ScenarioRunnerBehaviour.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -28,6 +28,7 @@
 import org.jbehave.scenario.steps.StepCreator;
 import org.jbehave.scenario.steps.StepResult;
 import org.jbehave.scenario.steps.Steps;
+import org.jbehave.scenario.steps.StepCreator.Stage;
 import org.junit.Test;
 import org.mockito.InOrder;
 
@@ -68,6 +69,7 @@
         when(creator.createStepsFrom(scenarioDefinition2, tableRow, mySteps)).thenReturn(new Step[] { successfulStep });
         when(creator.createStepsFrom(scenarioDefinition3, tableRow, mySteps)).thenReturn(
                 new Step[] { successfulStep, pendingStep });
+        givenStoryWithNoBeforeOrAfterSteps(storyDefinition, creator, mySteps);
 
         // When
         ErrorStrategy errorStrategy = mock(ErrorStrategy.class);
@@ -116,11 +118,15 @@
         Step successfulStep = mock(Step.class);
         when(successfulStep.perform()).thenReturn(StepResult.success("successfulStep"));
         Step anotherSuccessfulStep = mock(Step.class);
-        when(anotherSuccessfulStep.perform()).thenReturn(StepResult.success("anotherSuccessfulStep"));
+        when(anotherSuccessfulStep.perform()).thenReturn(StepResult.success("anotherSuccessfulStep"));        
+        givenStoryWithNoBeforeOrAfterSteps(storyDefinition1, creator, mySteps);
         when(creator.createStepsFrom(scenarioDefinition1, tableRow, mySteps)).thenReturn(new Step[] { successfulStep });
+        givenStoryWithNoBeforeOrAfterSteps(storyDefinition2, creator, mySteps);
         when(creator.createStepsFrom(scenarioDefinition2, tableRow, mySteps)).thenReturn(
                 new Step[] { anotherSuccessfulStep });
         when(scenarioDefiner.loadScenarioDefinitionsFor("/path/to/given/scenario1")).thenReturn(storyDefinition1);
+        givenStoryWithNoBeforeOrAfterSteps(storyDefinition1, creator, mySteps);
+        givenStoryWithNoBeforeOrAfterSteps(storyDefinition2, creator, mySteps);
         ErrorStrategy errorStrategy = mock(ErrorStrategy.class);
 
         // When
@@ -155,10 +161,12 @@
         when(thirdStepNormal.doNotPerform()).thenReturn(StepResult.notPerformed("Then I should not be performed"));
         when(fourthStepAlsoPending.doNotPerform()).thenReturn(
                 StepResult.notPerformed("Then I should not be performed either"));
+        StoryDefinition storyDefinition = new StoryDefinition(new ScenarioDefinition(""));
+        givenStoryWithNoBeforeOrAfterSteps(storyDefinition, creator, mySteps);
 
         // When
         ScenarioRunner runner = new ScenarioRunner();
-        runner.run(new StoryDefinition(new ScenarioDefinition("")), configurationWith(reporter, creator), false,
+        runner.run(storyDefinition, configurationWith(reporter, creator), false,
                 mySteps);
 
         // Then
@@ -188,12 +196,13 @@
         Steps mySteps = mock(Steps.class);
         when(creator.createStepsFrom((ScenarioDefinition) anyObject(), eq(tableRow), eq(mySteps))).thenReturn(
                 new Step[] { firstStepExceptional, secondStepNotPerformed });
-        StoryDefinition story = new StoryDefinition(new ScenarioDefinition(""));
+        StoryDefinition storyDefinition = new StoryDefinition(new ScenarioDefinition(""));
+        givenStoryWithNoBeforeOrAfterSteps(storyDefinition, creator, mySteps);
         boolean embeddedStory = false;
 
         // When
         ScenarioRunner runner = new ScenarioRunner();
-        runner.run(story, configurationWith(reporter, creator, errorStrategy), false, mySteps);
+        runner.run(storyDefinition, configurationWith(reporter, creator, errorStrategy), false, mySteps);
 
         // Then
         verify(firstStepExceptional).perform();
@@ -223,10 +232,13 @@
         ScenarioDefinition scenario2 = mock(ScenarioDefinition.class);
         when(creator.createStepsFrom(scenario1, tableRow, mySteps)).thenReturn(new Step[] { pendingStep });
         when(creator.createStepsFrom(scenario2, tableRow, mySteps)).thenReturn(new Step[] { secondStep });
+        StoryDefinition storyDefinition = new StoryDefinition(scenario1, scenario2);
+        givenStoryWithNoBeforeOrAfterSteps(storyDefinition, creator, mySteps);
 
+
         // When
         ScenarioRunner runner = new ScenarioRunner();
-        runner.run(new StoryDefinition(scenario1, scenario2), configurationWith(reporter, creator), false, mySteps);
+        runner.run(storyDefinition, configurationWith(reporter, creator), false, mySteps);
 
         // Then
         verify(pendingStep).perform();
@@ -235,6 +247,30 @@
     }
 
     @Test
+    public void shouldRunBeforeAndAfterStorySteps() throws Throwable {
+        // Given
+        ScenarioReporter reporter = mock(ScenarioReporter.class);
+        Step beforeStep = mock(Step.class);
+        Step afterStep = mock(Step.class);
+        when(beforeStep.perform()).thenReturn(StepResult.success("beforeStep"));
+        when(afterStep.perform()).thenReturn(StepResult.success("secondStep"));
+        StepCreator creator = mock(StepCreator.class);
+        CandidateSteps mySteps = mock(Steps.class);
+        StoryDefinition storyDefinition = new StoryDefinition();
+        when(creator.createStepsFrom(storyDefinition, Stage.BEFORE, mySteps)).thenReturn(new Step[] { beforeStep });
+        when(creator.createStepsFrom(storyDefinition, Stage.AFTER, mySteps)).thenReturn(new Step[] { afterStep });
+
+        // When
+        ScenarioRunner runner = new ScenarioRunner();
+        runner.run(storyDefinition, configurationWith(reporter, creator), false, mySteps);
+
+        // Then
+        verify(beforeStep).perform();
+        verify(afterStep).perform();
+    }
+    
+    
+    @Test
     public void shouldHandlePendingStepsAccordingToStrategy() throws Throwable {
         // Given
         ScenarioReporter reporter = mock(ScenarioReporter.class);
@@ -246,16 +282,24 @@
         Steps mySteps = mock(Steps.class);
         when(creator.createStepsFrom((ScenarioDefinition) anyObject(), eq(tableRow), eq(mySteps))).thenReturn(
                 new Step[] { pendingStep });
+        StoryDefinition storyDefinition = new StoryDefinition(new ScenarioDefinition(""));
+        givenStoryWithNoBeforeOrAfterSteps(storyDefinition, creator, mySteps);
 
+
         // When
         ScenarioRunner runner = new ScenarioRunner();
-        runner.run(new StoryDefinition(new ScenarioDefinition("")), configurationWithPendingStrategy(creator, reporter,
+        runner.run(storyDefinition, configurationWithPendingStrategy(creator, reporter,
                 strategy), false, mySteps);
 
         // Then
         verify(strategy).handleError(pendingResult.getThrowable());
     }
 
+    private void givenStoryWithNoBeforeOrAfterSteps(StoryDefinition storyDefinition1, StepCreator creator, CandidateSteps mySteps) {
+        when(creator.createStepsFrom(storyDefinition1, Stage.BEFORE, mySteps)).thenReturn(new Step[] {});
+        when(creator.createStepsFrom(storyDefinition1, Stage.AFTER, mySteps)).thenReturn(new Step[] {});
+    }
+
     private Configuration configurationWithPendingStrategy(StepCreator creator, ScenarioReporter reporter,
             PendingErrorStrategy strategy) {
         return configurationWith(new ClasspathScenarioDefiner(), reporter, creator,

Modified: trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/steps/UnmatchedToPendingStepCreatorBehaviour.java (1560 => 1561)

--- trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/steps/UnmatchedToPendingStepCreatorBehaviour.java	2010-02-07 18:44:35 UTC (rev 1560)
+++ trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/steps/UnmatchedToPendingStepCreatorBehaviour.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -7,33 +7,35 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.jbehave.scenario.definition.ScenarioDefinition;
+import org.jbehave.scenario.definition.StoryDefinition;
+import org.jbehave.scenario.steps.StepCreator.Stage;
 import org.junit.Test;
 
 public class UnmatchedToPendingStepCreatorBehaviour {
 
     private Map<String, String> tableRow = new HashMap<String, String>();
 
-	@Test
+    @Test
     public void shouldMatchUpStepsAndScenarioDefinitionToCreateExecutableSteps() {
         // Given
         UnmatchedToPendingStepCreator creator = new UnmatchedToPendingStepCreator();
-        
+
         CandidateStep candidate = mock(CandidateStep.class);
         CandidateSteps steps = mock(Steps.class);
         Step executableStep = mock(Step.class);
-        
+
         when(candidate.matches("my step")).thenReturn(true);
         when(candidate.createFrom(tableRow, "my step")).thenReturn(executableStep);
-        when(steps.getSteps()).thenReturn(new CandidateStep[] {candidate});
-        
+        when(steps.getSteps()).thenReturn(new CandidateStep[] { candidate });
+
         // When
-        Step[] executableSteps = creator.createStepsFrom(new ScenarioDefinition("", asList("my step")), tableRow, steps);
-        
+        Step[] executableSteps = creator
+                .createStepsFrom(new ScenarioDefinition("", asList("my step")), tableRow, steps);
+
         // Then
         ensureThat(executableSteps.length, equalTo(1));
         ensureThat(executableSteps[0], equalTo(executableStep));
@@ -43,52 +45,85 @@
     public void shouldProvidePendingStepsForAnyStepsWhichAreNotAvailable() {
         // Given
         UnmatchedToPendingStepCreator creator = new UnmatchedToPendingStepCreator();
-        
+
         CandidateStep candidate = mock(CandidateStep.class);
         CandidateSteps steps = mock(Steps.class);
-        
+
         when(candidate.matches("my step")).thenReturn(false);
-        when(steps.getSteps()).thenReturn(new CandidateStep[] {candidate});
-        
+        when(steps.getSteps()).thenReturn(new CandidateStep[] { candidate });
+
         // When
-        Step[] executableSteps = creator.createStepsFrom(new ScenarioDefinition("", asList("my step")), tableRow, steps);
+        Step[] executableSteps = creator
+                .createStepsFrom(new ScenarioDefinition("", asList("my step")), tableRow, steps);
         // Then
         ensureThat(executableSteps.length, equalTo(1));
         StepResult result = executableSteps[0].perform();
         ensureThat(result.getThrowable().getMessage(), equalTo("Pending: my step"));
     }
-    
+
     @SuppressWarnings("unchecked")
-	@Test
+    @Test
     public void shouldPrependBeforeScenarioAndAppendAfterScenarioAnnotatedSteps() {
-    	//Given some steps classes which run different steps before and after scenarios
-    	Steps steps1 = mock(Steps.class);
-    	Steps steps2 = mock(Steps.class);
-    	Step stepBefore1 = mock(Step.class);
-    	Step stepBefore2 = mock(Step.class);
-    	Step stepAfter1 = mock(Step.class);
-    	Step stepAfter2 = mock(Step.class);
+        // Given some steps classes which run different steps before and after
+        // scenarios
+        CandidateSteps steps1 = mock(Steps.class);
+        CandidateSteps steps2 = mock(Steps.class);
+        Step stepBefore1 = mock(Step.class);
+        Step stepBefore2 = mock(Step.class);
+        Step stepAfter1 = mock(Step.class);
+        Step stepAfter2 = mock(Step.class);
 
-    	when(steps1.runBeforeScenario()).thenReturn(Arrays.asList(stepBefore1));
-    	when(steps2.runBeforeScenario()).thenReturn(Arrays.asList(stepBefore2));
-    	when(steps1.runAfterScenario()).thenReturn(Arrays.asList(stepAfter1));
-    	when(steps2.runAfterScenario()).thenReturn(Arrays.asList(stepAfter2));
+        when(steps1.runBeforeScenario()).thenReturn(asList(stepBefore1));
+        when(steps2.runBeforeScenario()).thenReturn(asList(stepBefore2));
+        when(steps1.runAfterScenario()).thenReturn(asList(stepAfter1));
+        when(steps2.runAfterScenario()).thenReturn(asList(stepAfter2));
 
-    	// And which have a 'normal' step that matches our scenario
+        // And which have a 'normal' step that matches our scenario
         CandidateStep candidate = mock(CandidateStep.class);
         Step normalStep = mock(Step.class);
-        
+
         when(candidate.matches("my step")).thenReturn(true);
         when(candidate.createFrom(tableRow, "my step")).thenReturn(normalStep);
-        when(steps1.getSteps()).thenReturn(new CandidateStep[] {candidate});
+        when(steps1.getSteps()).thenReturn(new CandidateStep[] { candidate });
         when(steps2.getSteps()).thenReturn(new CandidateStep[] {});
-    	
+
         // When we create the series of steps for the scenario
-    	UnmatchedToPendingStepCreator creator = new UnmatchedToPendingStepCreator();
-    	Step[] executableSteps = creator.createStepsFrom(new ScenarioDefinition("", asList("my step")), tableRow, steps1, steps2);
-    	
-    	// Then all before and after steps should be added
-    	ensureThat(executableSteps, array(equalTo(stepBefore2), equalTo(stepBefore1), equalTo(normalStep), equalTo(stepAfter1), equalTo(stepAfter2)));
+        UnmatchedToPendingStepCreator creator = new UnmatchedToPendingStepCreator();
+        Step[] executableSteps = creator.createStepsFrom(new ScenarioDefinition("", asList("my step")), tableRow,
+                steps1, steps2);
+
+        // Then all before and after steps should be added
+        ensureThat(executableSteps, array(equalTo(stepBefore2), equalTo(stepBefore1), equalTo(normalStep),
+                equalTo(stepAfter1), equalTo(stepAfter2)));
     }
 
+    @SuppressWarnings("unchecked")
+    @Test
+    public void shouldReturnBeforeAndAfterStoryAnnotatedSteps() {
+        // Given some steps classes which run different steps before and after
+        // story
+        CandidateSteps steps1 = mock(Steps.class);
+        CandidateSteps steps2 = mock(Steps.class);
+        Step stepBefore1 = mock(Step.class);
+        Step stepBefore2 = mock(Step.class);
+        Step stepAfter1 = mock(Step.class);
+        Step stepAfter2 = mock(Step.class);
+
+        when(steps1.runBeforeStory()).thenReturn(asList(stepBefore1));
+        when(steps2.runBeforeStory()).thenReturn(asList(stepBefore2));
+        when(steps1.runAfterStory()).thenReturn(asList(stepAfter1));
+        when(steps2.runAfterStory()).thenReturn(asList(stepAfter2));
+
+        // When we create the series of steps for the scenario
+        UnmatchedToPendingStepCreator creator = new UnmatchedToPendingStepCreator();
+        Step[] beforeSteps = creator.createStepsFrom(new StoryDefinition(new ScenarioDefinition("")), Stage.BEFORE,
+                steps1, steps2);
+        Step[] afterSteps = creator.createStepsFrom(new StoryDefinition(new ScenarioDefinition("")), Stage.AFTER,
+                steps1, steps2);
+
+        // Then all before and after steps should be added
+        ensureThat(beforeSteps, array(equalTo(stepBefore1), equalTo(stepBefore2)));
+        ensureThat(afterSteps, array(equalTo(stepAfter1), equalTo(stepAfter2)));
+    }
+
 }

Modified: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/ScenarioRunner.java (1560 => 1561)

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/ScenarioRunner.java	2010-02-07 18:44:35 UTC (rev 1560)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/ScenarioRunner.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -14,6 +14,7 @@
 import org.jbehave.scenario.reporters.ScenarioReporter;
 import org.jbehave.scenario.steps.CandidateSteps;
 import org.jbehave.scenario.steps.Step;
+import org.jbehave.scenario.steps.StepCreator;
 import org.jbehave.scenario.steps.StepResult;
 
 /**
@@ -31,6 +32,7 @@
     private ScenarioReporter reporter;
     private ErrorStrategy errorStrategy;
     private Throwable throwable;
+    private StepCreator stepCreator;
 
     public void run(Class<? extends RunnableScenario> scenarioClass, Configuration configuration, CandidateSteps... candidateSteps) throws Throwable {
 		StoryDefinition story = configuration.forDefiningScenarios().loadScenarioDefinitionsFor(scenarioClass);
@@ -49,13 +51,15 @@
     }
     
     public void run(StoryDefinition story, Configuration configuration, boolean embeddedStory, CandidateSteps... candidateSteps) throws Throwable {
+        stepCreator = configuration.forCreatingSteps();
         reporter = configuration.forReportingScenarios();
         pendingStepStrategy = configuration.forPendingSteps();
         errorStrategy = configuration.forHandlingErrors();
         currentStrategy = ErrorStrategy.SILENT;
         throwable = null;
         
-        reporter.beforeStory(story, embeddedStory);            
+        reporter.beforeStory(story, embeddedStory);          
+        runSteps(stepCreator.createStepsFrom(story, StepCreator.Stage.BEFORE, candidateSteps), embeddedStory);
         for (ScenarioDefinition scenario : story.getScenarios()) {
     		reporter.beforeScenario(scenario.getTitle());
         	runGivenScenarios(configuration, scenario, candidateSteps); // first run any given scenarios, if any
@@ -66,11 +70,28 @@
         	}
     		reporter.afterScenario();
         }
+        runSteps(stepCreator.createStepsFrom(story, StepCreator.Stage.AFTER, candidateSteps), embeddedStory);
         reporter.afterStory(embeddedStory);            
         currentStrategy.handleError(throwable);
     }
 
-	private void runGivenScenarios(Configuration configuration,
+	
+    /**
+     * Runs a list of steps.  The running can be skipped in certain cases,
+     * e.g. when running in embedded story mode.
+     * 
+     * @param steps the Steps to run
+     * @param skip the boolean flag to skip running
+     */
+    private void runSteps(Step[] steps, boolean skip) {
+        if ( skip ) return; 
+        state = new FineSoFar();
+        for (Step step : steps) {
+            state.run(step);
+        }
+    }
+	
+    private void runGivenScenarios(Configuration configuration,
 			ScenarioDefinition scenario, CandidateSteps... candidateSteps)
 			throws Throwable {
 		List<String> givenScenarios = scenario.getGivenScenarios();
@@ -101,11 +122,8 @@
 
 	private void runScenario(Configuration configuration,
 			ScenarioDefinition scenario, Map<String, String> tableRow, CandidateSteps... candidateSteps) {
-		Step[] steps = configuration.forCreatingSteps().createStepsFrom(scenario, tableRow, candidateSteps);
-		state = new FineSoFar();
-		for (Step step : steps) {
-		    state.run(step);
-		}
+        Step[] steps = stepCreator.createStepsFrom(scenario, tableRow, candidateSteps);
+		runSteps(steps, false);
 	};
 
     private class SomethingHappened implements State {

Added: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/annotations/AfterStory.java (0 => 1561)

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/annotations/AfterStory.java	                        (rev 0)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/annotations/AfterStory.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -0,0 +1,12 @@
+package org.jbehave.scenario.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+...@retention(RetentionPolicy.RUNTIME)
+...@target(ElementType.METHOD)
+public @interface AfterStory {
+
+}

Added: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/annotations/BeforeStory.java (0 => 1561)

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/annotations/BeforeStory.java	                        (rev 0)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/annotations/BeforeStory.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -0,0 +1,12 @@
+package org.jbehave.scenario.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+...@retention(RetentionPolicy.RUNTIME)
+...@target(ElementType.METHOD)
+public @interface BeforeStory {
+
+}

Modified: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/CandidateSteps.java (1560 => 1561)

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/CandidateSteps.java	2010-02-07 18:44:35 UTC (rev 1560)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/CandidateSteps.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -1,6 +1,6 @@
 package org.jbehave.scenario.steps;
 
-import java.util.Collection;
+import java.util.List;
 
 /**
  * Represents the list of candidate steps that can be performed
@@ -8,31 +8,46 @@
 public interface CandidateSteps {
 
     /**
-     * Return all the steps that can be performed by the implementing class
+     * Return all the candidate steps that can be performed by the implementing class
      * 
      * @return The list of candidate steps
      */
     CandidateStep[] getSteps();
 
     /**
-     * Return all the steps that can be performed by the given class
+     * Return all the candidate steps that can be performed by the given class
      * 
      * @return The list of candidate steps
      */
     CandidateStep[] getSteps(Class<?> stepsClass);
 
     /**
-     * Return all steps to run before scenario
+     * Return all the executable steps to run before each story
      * 
      * @return The list of steps 
      */
-    Collection<? extends Step> runBeforeScenario();
+    List<Step> runBeforeStory();
 
     /**
-     * Return all steps to run after scenario
+     * Return all the executable steps to run after each story
      * 
      * @return The list of steps 
      */
-    Collection<? extends Step> runAfterScenario();
+    List<Step> runAfterStory();
 
+    /**
+     * Return all the executable steps to run before each scenario
+     * 
+     * @return The list of steps 
+     */
+    List<Step> runBeforeScenario();
+
+    /**
+     * Return all the executable steps to run after each scenario
+     * 
+     * @return The list of steps 
+     */
+    List<Step> runAfterScenario();
+
+
 }

Modified: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/StepCreator.java (1560 => 1561)

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/StepCreator.java	2010-02-07 18:44:35 UTC (rev 1560)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/StepCreator.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -3,14 +3,21 @@
 import java.util.Map;
 
 import org.jbehave.scenario.definition.ScenarioDefinition;
+import org.jbehave.scenario.definition.StoryDefinition;
 
 /**
  * Represents the strategy for the creation of executable {...@link Step}s from a
- * given scenario definition matching a list of {...@link CandidateSteps}.
+ * given story or scenario definition matching a list of {...@link CandidateSteps}.
  */
 public interface StepCreator {
 
-	Step[] createStepsFrom(ScenarioDefinition scenarioDefinition,
-			Map<String, String> tableRow, CandidateSteps... candidateSteps);
+    enum Stage {
+        BEFORE, AFTER
+    };
 
+    Step[] createStepsFrom(StoryDefinition storyDefinition, Stage stage, CandidateSteps... candidateSteps);
+
+    Step[] createStepsFrom(ScenarioDefinition scenarioDefinition, Map<String, String> tableRow,
+            CandidateSteps... candidateSteps);
+
 }

Modified: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/Steps.java (1560 => 1561)

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/Steps.java	2010-02-07 18:44:35 UTC (rev 1560)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/Steps.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -16,9 +16,11 @@
 import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.commons.lang.builder.ToStringStyle;
 import org.jbehave.scenario.annotations.AfterScenario;
+import org.jbehave.scenario.annotations.AfterStory;
 import org.jbehave.scenario.annotations.Alias;
 import org.jbehave.scenario.annotations.Aliases;
 import org.jbehave.scenario.annotations.BeforeScenario;
+import org.jbehave.scenario.annotations.BeforeStory;
 import org.jbehave.scenario.annotations.Given;
 import org.jbehave.scenario.annotations.Then;
 import org.jbehave.scenario.annotations.When;
@@ -208,6 +210,14 @@
         }
     }
 
+    public List<Step> runBeforeStory() {
+        return stepsHaving(BeforeStory.class, new OkayToRun());
+    }
+
+    public List<Step> runAfterStory() {
+        return stepsHaving(AfterStory.class, new OkayToRun());
+    }
+
     public List<Step> runBeforeScenario() {
         return stepsHaving(BeforeScenario.class, new OkayToRun());
     }
@@ -220,7 +230,7 @@
         return steps;
     }
 
-    private List<Step> stepsHaving(final Class<? extends Annotation> annotationClass, final StepPart forScenarios) {
+    List<Step> stepsHaving(final Class<? extends Annotation> annotationClass, final StepPart forScenarios) {
         List<Step> steps = new ArrayList<Step>();
         Method[] methods;
         if (instance == null) {
@@ -270,7 +280,7 @@
         return steps;
     }
 
-    private class OkayToRun implements StepPart {
+    class OkayToRun implements StepPart {
         public StepResult run(final Class<? extends Annotation> annotation, Method method) {
             try {
                 method.invoke(instance);

Modified: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/UnmatchedToPendingStepCreator.java (1560 => 1561)

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/UnmatchedToPendingStepCreator.java	2010-02-07 18:44:35 UTC (rev 1560)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/UnmatchedToPendingStepCreator.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -5,23 +5,41 @@
 import java.util.Map;
 
 import org.jbehave.scenario.definition.ScenarioDefinition;
+import org.jbehave.scenario.definition.StoryDefinition;
 
 /**
  * StepCreator that marks unmatched steps as {...@link StepResult.Pending}
  */
 public class UnmatchedToPendingStepCreator implements StepCreator {
 
+    public Step[] createStepsFrom(StoryDefinition storyDefinition, Stage stage, CandidateSteps... candidateSteps) {
+        List<Step> steps = new ArrayList<Step>();
+        for (CandidateSteps candidates : candidateSteps) {
+            switch (stage) {
+                case BEFORE:
+                    steps.addAll(candidates.runBeforeStory());
+                    break;
+                case AFTER:
+                    steps.addAll(candidates.runAfterStory());
+                    break;
+                default:
+                    break;
+            }
+        }
+        return steps.toArray(new Step[steps.size()]);
+    }
+
     public Step[] createStepsFrom(ScenarioDefinition scenario, Map<String, String> tableRow,
             CandidateSteps... candidateSteps) {
         List<Step> steps = new ArrayList<Step>();
 
-        addAllNormalSteps(scenario, steps, tableRow, candidateSteps);
-        addBeforeAndAfterSteps(steps, candidateSteps);
+        addMatchedScenarioSteps(scenario, steps, tableRow, candidateSteps);
+        addBeforeAndAfterScenarioSteps(steps, candidateSteps);
 
         return steps.toArray(new Step[steps.size()]);
     }
 
-    private void addBeforeAndAfterSteps(List<Step> steps, CandidateSteps[] candidateSteps) {
+    private void addBeforeAndAfterScenarioSteps(List<Step> steps, CandidateSteps[] candidateSteps) {
         for (CandidateSteps candidates : candidateSteps) {
             steps.addAll(0, candidates.runBeforeScenario());
         }
@@ -31,13 +49,13 @@
         }
     }
 
-    private void addAllNormalSteps(ScenarioDefinition scenarioDefinition, List<Step> steps,
+    private void addMatchedScenarioSteps(ScenarioDefinition scenarioDefinition, List<Step> steps,
             Map<String, String> tableRow, CandidateSteps... candidateSteps) {
         for (String stringStep : scenarioDefinition.getSteps()) {
             Step step = new PendingStep(stringStep);
             for (CandidateSteps candidates : candidateSteps) {
                 for (CandidateStep candidate : candidates.getSteps()) {
-                    if (candidate.ignore(stringStep)) {
+                    if (candidate.ignore(stringStep)) { // ignorable steps are added so they can be reported
                         step = new IgnorableStep(stringStep);
                         break;
                     }                        
@@ -50,4 +68,5 @@
             steps.add(step);
         }
     }
+
 }

Modified: trunk/core/jbehave-pico/src/behaviour/java/org/jbehave/scenario/steps/pico/PicoStepsFactoryBehaviour.java (1560 => 1561)

--- trunk/core/jbehave-pico/src/behaviour/java/org/jbehave/scenario/steps/pico/PicoStepsFactoryBehaviour.java	2010-02-07 18:44:35 UTC (rev 1560)
+++ trunk/core/jbehave-pico/src/behaviour/java/org/jbehave/scenario/steps/pico/PicoStepsFactoryBehaviour.java	2010-02-08 11:53:18 UTC (rev 1561)
@@ -60,7 +60,7 @@
 
     private void assertFooStepsFound(CandidateSteps[] steps) throws NoSuchFieldException, IllegalAccessException {
         assertEquals(1, steps.length);
-        assertTrue(steps[0] instanceof Steps);
+        assertTrue(steps[0] instanceof CandidateSteps);
         Object instance = stepsInstance.get(steps[0]);
         assertTrue(instance instanceof FooSteps);
     }


To unsubscribe from this list please visit:

http://xircles.codehaus.org/manage_email

Reply via email to