Title: [1620] trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps: JBEHAVE-278: Enhanced candidate step matching to be aware of the previous step type when matching AND steps.

Diff

Added: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/scenarios/AndStep.java (0 => 1620)

--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/scenarios/AndStep.java	                        (rev 0)
+++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/scenarios/AndStep.java	2010-05-01 10:46:50 UTC (rev 1620)
@@ -0,0 +1,52 @@
+package org.jbehave.examples.trader.scenarios;
+
+import org.jbehave.scenario.JUnitScenario;
+import org.jbehave.scenario.MostUsefulConfiguration;
+import org.jbehave.scenario.annotations.Given;
+import org.jbehave.scenario.annotations.When;
+import org.jbehave.scenario.parser.ClasspathScenarioDefiner;
+import org.jbehave.scenario.parser.PatternScenarioParser;
+import org.jbehave.scenario.parser.ScenarioDefiner;
+import org.jbehave.scenario.parser.UnderscoredCamelCaseResolver;
+import org.jbehave.scenario.reporters.PrintStreamScenarioReporter;
+import org.jbehave.scenario.reporters.ScenarioReporter;
+import org.jbehave.scenario.steps.PrintStreamStepMonitor;
+import org.jbehave.scenario.steps.StepsConfiguration;
+import org.jbehave.scenario.steps.StepsFactory;
+
+public class AndStep extends JUnitScenario {
+
+	public AndStep() {
+		useConfiguration(new MostUsefulConfiguration() {
+			@Override
+			public ScenarioDefiner forDefiningScenarios() {
+				return new ClasspathScenarioDefiner(
+						new UnderscoredCamelCaseResolver(".scenario"),
+						new PatternScenarioParser(keywords()));
+			}
+
+			@Override
+			public ScenarioReporter forReportingScenarios() {
+				return new PrintStreamScenarioReporter();
+			}
+
+		});
+
+		StepsConfiguration configuration = new StepsConfiguration();
+        configuration.useMonitor(new PrintStreamStepMonitor());
+		addSteps(new StepsFactory(configuration).createCandidateSteps(new AndSteps()));
+	}
+
+	public static class AndSteps {
+		@Given("the wind blows")
+		public void givenWindBlows() {
+			System.err.println("given the wind blows");
+		}
+
+		@When("the wind blows")
+		public void whenWindBlows() {
+			System.err.println("when the wind blows");
+		}
+
+	}
+}

Added: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/scenarios/and_step.scenario (0 => 1620)

--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/scenarios/and_step.scenario	                        (rev 0)
+++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/scenarios/and_step.scenario	2010-05-01 10:46:50 UTC (rev 1620)
@@ -0,0 +1,10 @@
+Scenario: An initial AND step should be marked as pending as there is not previous step
+
+And the wind blows
+
+Scenario: AND steps should match the previous step type
+
+Given the wind blows
+And the wind blows
+When the wind blows
+And the wind blows
\ No newline at end of file

Modified: trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/steps/CandidateStepBehaviour.java (1619 => 1620)

--- trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/steps/CandidateStepBehaviour.java	2010-04-27 22:13:11 UTC (rev 1619)
+++ trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/steps/CandidateStepBehaviour.java	2010-05-01 10:46:50 UTC (rev 1620)
@@ -5,6 +5,7 @@
 import static org.hamcrest.CoreMatchers.nullValue;
 import static org.jbehave.Ensure.ensureThat;
 import static org.jbehave.Ensure.not;
+import static org.jbehave.scenario.steps.StepType.AND;
 import static org.jbehave.scenario.steps.StepType.GIVEN;
 import static org.jbehave.scenario.steps.StepType.THEN;
 import static org.jbehave.scenario.steps.StepType.WHEN;
@@ -46,18 +47,19 @@
 		map.put(GIVEN, "Given");
 		map.put(WHEN, "When");
 		map.put(THEN, "Then");
+		map.put(AND, "And");
 		return map;
 	}
            
     @Test
-    public void shouldMatchASimpleString() throws Exception {
+    public void shouldMatchAStepWithoutArguments() throws Exception {
         CandidateStep candidateStep = new CandidateStep("I laugh", DEFAULT_PRIORITY, GIVEN,
                 SomeSteps.class.getMethod("aMethod"), null, PATTERN_BUILDER, new ParameterConverters(), startingWords);
         ensureThat(candidateStep.matches("Given I laugh"));
     }
 
     @Test
-    public void shouldMatchAStringWithArguments() throws Exception {
+    public void shouldMatchAStepWithArguments() throws Exception {
         CandidateStep candidateStep = new CandidateStep("windows on the $nth floor", DEFAULT_PRIORITY, WHEN, SomeSteps.class
                         		        .getMethod("aMethod"), null, PATTERN_BUILDER, new ParameterConverters(), startingWords);
         ensureThat(candidateStep.matches("When windows on the 1st floor"));
@@ -65,6 +67,14 @@
     }
 
     @Test
+    public void shouldMatchAndStepsOnlyWithPreviousStep() throws Exception {
+        CandidateStep candidateStep = new CandidateStep("windows on the $nth floor", DEFAULT_PRIORITY, WHEN, SomeSteps.class
+                        		        .getMethod("aMethod"), null, PATTERN_BUILDER, new ParameterConverters(), startingWords);
+        ensureThat(not(candidateStep.matches("And windows on the 1st floor")));
+        ensureThat(candidateStep.matches("And windows on the 1st floor", "When windows on the 1st floor"));
+    }
+    
+    @Test
     public void shouldProvideARealStepUsingTheMatchedString() throws Exception {
         SomeSteps someSteps = new SomeSteps();
         CandidateStep candidateStep = new CandidateStep("I live on the $nth floor", DEFAULT_PRIORITY, THEN, SomeSteps.class.getMethod(
@@ -270,9 +280,13 @@
         CandidateStep[] candidateSteps = steps.getSteps();
         ensureThat(candidateSteps.length, equalTo(2));
         candidateSteps[0].createFrom(tableRow, "Given foo named xyz").perform();
+        candidateSteps[0].createFrom(tableRow, "And foo named xyz").perform();
         candidateSteps[1].createFrom(tableRow, "When foo named Bar").perform();
+        candidateSteps[1].createFrom(tableRow, "And foo named Bar").perform();
         ensureThat(steps.givenName, equalTo("xyz"));
+        ensureThat(steps.givenTimes, equalTo(2));
         ensureThat(steps.whenName, equalTo("Bar"));
+        ensureThat(steps.whenTimes, equalTo(2));
     }
 
 	@Test(expected=StartingWordNotFound.class)
@@ -289,15 +303,19 @@
     static class NamedTypeSteps extends Steps {
         String givenName;
         String whenName;
+		int givenTimes;
+		int whenTimes;
 
         @Given("foo named $name")
         public void givenFoo(String name) {
         	givenName = name;
+        	givenTimes++;
         }
 
         @When("foo named $name")
         public void whenFoo(String name) {
         	whenName = name;
+        	whenTimes++;
         }
 
     }

Modified: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/CandidateStep.java (1619 => 1620)

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/CandidateStep.java	2010-04-27 22:13:11 UTC (rev 1619)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/CandidateStep.java	2010-05-01 10:46:50 UTC (rev 1620)
@@ -90,16 +90,34 @@
     }
 
     public boolean matches(String stepAsString) {
+    	return matches(stepAsString, null);
+    }
+
+    public boolean matches(String stepAsString, String previousAsString) {
         try {
-            Matcher matcher = matcherForStep(stepAsString);
-            boolean matches = matcher.matches();
-            stepMonitor.stepMatchesPattern(stepAsString, matches, pattern.pattern());
-            return matches;
+        	boolean matchesType = true;
+        	if ( isAndStep(stepAsString) ){
+        		if ( previousAsString == null ){
+        			matchesType = false; // cannot handle AND step with no previous step
+        		} else {
+        			// previous step type should match candidate step type
+        			matchesType = startingWordFor(stepType).equals(findStartingWord(previousAsString));
+        		}
+        	}
+            stepMonitor.stepMatchesType(stepAsString, previousAsString, matchesType, stepType);
+            boolean matchesPattern = matcherForStep(stepAsString).matches();
+            stepMonitor.stepMatchesPattern(stepAsString, matchesPattern, pattern.pattern());
+            // must match both type and pattern
+            return matchesType && matchesPattern;
         } catch (StartingWordNotFound e) {
             return false;
         }
     }
 
+	private boolean isAndStep(String stepAsString) {
+		return stepAsString.startsWith(startingWordFor(StepType.AND));
+	}
+
     private String trimStartingWord(String word, String step) {
         return step.substring(word.length() + 1); // 1 for the space after
     }

Modified: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/PrintStreamStepMonitor.java (1619 => 1620)

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/PrintStreamStepMonitor.java	2010-04-27 22:13:11 UTC (rev 1619)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/PrintStreamStepMonitor.java	2010-05-01 10:46:50 UTC (rev 1620)
@@ -10,8 +10,9 @@
  * {...@link System.out}.
  */
 public class PrintStreamStepMonitor implements StepMonitor {
-	
+
 	private static final String CONVERTED_VALUE_OF_TYPE = "Converted value ''{0}'' of type ''{1}'' to ''{2}'' with converter ''{3}''";
+	private static final String STEP_MATCHES_TYPE = "Step ''{0}'' (with previous step ''{1}'') ''{2}'' type ''{3}''";
 	private static final String STEP_MATCHES_PATTERN = "Step ''{0}'' {1} pattern ''{2}''";
 	private static final String MATCHES = "matches";
 	private static final String DOES_NOT_MATCH = "does not match";
@@ -33,6 +34,13 @@
 		this.output = output;
 	}
 
+	public void stepMatchesType(String step, String previous, boolean matches,
+			StepType stepType) {
+		String message = format(STEP_MATCHES_TYPE, step, previous,
+				(matches ? MATCHES : DOES_NOT_MATCH), stepType);
+		print(output, message);
+	}
+
 	public void stepMatchesPattern(String step, boolean matches, String pattern) {
 		String message = format(STEP_MATCHES_PATTERN, step, (matches ? MATCHES
 				: DOES_NOT_MATCH), pattern);
@@ -57,32 +65,33 @@
 
 	public void usingParameterNameForArg(String name, int position) {
 		String message = format(USING_NAME_FOR_ARG, PARAMETER, name, position);
-		print(output, message);		
+		print(output, message);
 	}
 
 	public void usingTableAnnotatedNameForArg(String name, int position) {
-		String message = format(USING_NAME_FOR_ARG, TABLE_ANNOTATED, name, position);
-		print(output, message);		
+		String message = format(USING_NAME_FOR_ARG, TABLE_ANNOTATED, name,
+				position);
+		print(output, message);
 	}
 
 	public void usingTableParameterNameForArg(String name, int position) {
-		String message = format(USING_NAME_FOR_ARG, TABLE_PARAMETER, name, position);
-		print(output, message);		
+		String message = format(USING_NAME_FOR_ARG, TABLE_PARAMETER, name,
+				position);
+		print(output, message);
 	}
 
 	public void usingNaturalOrderForArg(int position) {
 		String message = format(USING_NATURAL_ORDER_FOR_ARG, position);
-		print(output, message);		
+		print(output, message);
 	}
 
 	public void foundArg(String arg, int position) {
 		String message = format(FOUND_ARG, arg, position);
-		print(output, message);		
+		print(output, message);
 	}
-	
+
 	protected void print(PrintStream output, String message) {
 		output.println(message);
 	}
 
-
 }

Modified: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/StepMonitor.java (1619 => 1620)

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/StepMonitor.java	2010-04-27 22:13:11 UTC (rev 1619)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/StepMonitor.java	2010-05-01 10:46:50 UTC (rev 1620)
@@ -9,8 +9,11 @@
  */
 public interface StepMonitor {
 
-    void stepMatchesPattern(String step, boolean matches, String pattern);
+	void stepMatchesType(String stepAsString, String previousAsString,
+			boolean matchesType, StepType stepType);
 
+	void stepMatchesPattern(String step, boolean matches, String pattern);
+
     void convertedValueOfType(String value, Type type, Object converted, Class<?> converterClass);
 
     void performing(String step);
@@ -26,4 +29,5 @@
 	void usingNaturalOrderForArg(int position);
 
 	void foundArg(String arg, int position);
+
 }

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

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/UnmatchedToPendingStepCreator.java	2010-04-27 22:13:11 UTC (rev 1619)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/UnmatchedToPendingStepCreator.java	2010-05-01 10:46:50 UTC (rev 1620)
@@ -56,7 +56,8 @@
     private void addMatchedScenarioSteps(ScenarioDefinition scenarioDefinition, List<Step> steps,
             Map<String, String> tableRow, CandidateSteps... candidateSteps) {
         List<CandidateStep> prioritised = prioritise(candidateSteps);
-        for (String stringStep : scenarioDefinition.getSteps()) {
+        String previousStep = null;
+        for (String stringStep : scenarioDefinition.getSteps()) {        	
             Step step = new PendingStep(stringStep);
             for (CandidateStep candidate : prioritised) {
                 if (candidate.ignore(stringStep)) { // ignorable steps are added
@@ -64,15 +65,24 @@
                     step = new IgnorableStep(stringStep);
                     break;
                 }
-                if (candidate.matches(stringStep)) {
+                if (matchesCandidate(stringStep, previousStep, candidate)) {
                     step = candidate.createFrom(tableRow, stringStep);
                     break;
                 }
             }
             steps.add(step);
+            previousStep = stringStep;
         }
     }
 
+	private boolean matchesCandidate(String stringStep, String previousStep,
+			CandidateStep candidate) {
+		if ( previousStep != null ){
+			return candidate.matches(stringStep, previousStep);			
+		}
+		return candidate.matches(stringStep);
+	}
+
     private List<CandidateStep> prioritise(CandidateSteps[] candidateSteps) {
         List<CandidateStep> steps = new ArrayList<CandidateStep>();
         for (CandidateSteps candidates : candidateSteps) {


To unsubscribe from this list please visit:

http://xircles.codehaus.org/manage_email

Reply via email to