- Revision
- 1007
- Author
- mauro
- Date
- 2008-11-02 04:57:28 -0600 (Sun, 02 Nov 2008)
Log Message
JBEHAVE-117: Throws exception if duplicate candidate steps found.
Modified Paths
Diff
Modified: trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/StepsBehaviour.java (1006 => 1007)
--- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/StepsBehaviour.java 2008-11-02 10:18:47 UTC (rev 1006) +++ trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/StepsBehaviour.java 2008-11-02 10:57:28 UTC (rev 1007) @@ -6,6 +6,7 @@ import java.util.List; import org.jbehave.scenario.annotations.AfterScenario; +import org.jbehave.scenario.steps.Steps.DuplicateCandidateStepFoundException; import org.junit.Test; public class StepsBehaviour { @@ -54,7 +55,7 @@ ensureThat(steps.afterSuccess); executableSteps.get(2).doNotPerform(); - ensureThat(steps.afterUnsuccess); + ensureThat(steps.afterFailure); } @Test @@ -70,9 +71,20 @@ executableSteps.get(2).perform(); - ensureThat(!steps.afterUnsuccess); // @AfterScenario(uponOutcome=FAILURE) is run after unsuccessful scenarios + ensureThat(!steps.afterFailure); // @AfterScenario(uponOutcome=FAILURE) is run after unsuccessful scenarios } + + @Test(expected=DuplicateCandidateStepFoundException.class) + public void shouldFailIfDuplicateStepsAreEncountered() { + DuplicateSteps steps = new DuplicateSteps(); + CandidateStep[] candidateSteps = steps.getSteps(); + + ensureThat(candidateSteps.length, equalTo(2)); + candidateSteps[0].createFrom("Given a given").perform(); + + } + public static class MySteps extends Steps { @@ -83,14 +95,14 @@ private boolean before; private boolean afterAny; private boolean afterSuccess; - private boolean afterUnsuccess; + private boolean afterFailure; @org.jbehave.scenario.annotations.Given("a given") @org.jbehave.scenario.annotations.Aliases(values={"a given alias", "another given alias"}) public void given() { givens++; } - + @org.jbehave.scenario.annotations.When("a when") @org.jbehave.scenario.annotations.Aliases(values={"a when alias", "another when alias"}) public void when() { @@ -120,9 +132,21 @@ @org.jbehave.scenario.annotations.AfterScenario(uponOutcome=AfterScenario.Outcome.FAILURE) public void afterUnsuccessfulScenarios() { - afterUnsuccess = true; + afterFailure = true; } } + + public static class DuplicateSteps extends Steps { + + @org.jbehave.scenario.annotations.Given("a given") + public void given() { + } + + @org.jbehave.scenario.annotations.Given("a given") + public void duplicateGiven() { + } + + } }
Modified: trunk/jbehave-core/src/java/org/jbehave/scenario/steps/CandidateStep.java (1006 => 1007)
--- trunk/jbehave-core/src/java/org/jbehave/scenario/steps/CandidateStep.java 2008-11-02 10:18:47 UTC (rev 1006) +++ trunk/jbehave-core/src/java/org/jbehave/scenario/steps/CandidateStep.java 2008-11-02 10:57:28 UTC (rev 1007) @@ -17,6 +17,7 @@ */ public class CandidateStep { + private final String stepAsString; private final Method method; private final CandidateSteps steps; private final StepMonitor stepMonitor; @@ -24,14 +25,15 @@ private final String[] startingWords; private final Pattern pattern; - public CandidateStep(String matchThis, Method method, CandidateSteps steps, StepPatternBuilder patterBuilder, + public CandidateStep(String stepAsString, Method method, CandidateSteps steps, StepPatternBuilder patterBuilder, StepMonitor stepMonitor, ParameterConverters parameterConverters, String... startingWords) { + this.stepAsString = stepAsString; this.method = method; this.steps = steps; this.stepMonitor = stepMonitor; this.parameterConverters = parameterConverters; this.startingWords = startingWords; - this.pattern = patterBuilder.buildPattern(matchThis); + this.pattern = patterBuilder.buildPattern(stepAsString); } public boolean matches(String step) { @@ -103,9 +105,17 @@ }; } + public String getStepAsString(){ + return stepAsString; + } + + public Pattern getPattern(){ + return pattern; + } + @Override public String toString() { - return pattern.pattern(); + return stepAsString; } }
Modified: trunk/jbehave-core/src/java/org/jbehave/scenario/steps/Steps.java (1006 => 1007)
--- trunk/jbehave-core/src/java/org/jbehave/scenario/steps/Steps.java 2008-11-02 10:18:47 UTC (rev 1006) +++ trunk/jbehave-core/src/java/org/jbehave/scenario/steps/Steps.java 2008-11-02 10:57:28 UTC (rev 1007) @@ -63,81 +63,100 @@ * </p> */ public class Steps implements CandidateSteps { - - private final StepsConfiguration configuration; - /** - * Creates Steps with default configuration - */ - public Steps() { - this(new StepsConfiguration()); - } + private final StepsConfiguration configuration; - /** - * Creates Steps with all default configuration except for custom starting - * keywords - * - * @param startingWords the words with which we expect steps in the - * scenarios to start - */ - public Steps(String... startingWords) { - this(new StepsConfiguration(startingWords)); - } - - /** - * Creates Steps with all default dependencies except for custom parameter converters. - * - * @param converters a set of converters which can change strings into other objects to pass into executable steps - */ - public Steps(ParameterConverters converters) { - this(new StepsConfiguration(converters)); - } + /** + * Creates Steps with default configuration + */ + public Steps() { + this(new StepsConfiguration()); + } - /** - * Creates Steps with all custom dependencies - * - * @param configuration the StepsConfiguration - */ - public Steps(StepsConfiguration configuration) { - this.configuration = configuration; - } + /** + * Creates Steps with all default configuration except for custom starting + * keywords + * + * @param startingWords + * the words with which we expect steps in the scenarios to start + */ + public Steps(String... startingWords) { + this(new StepsConfiguration(startingWords)); + } - public CandidateStep[] getSteps() { - return getSteps(this.getClass()); - } + /** + * Creates Steps with all default dependencies except for custom parameter + * converters. + * + * @param converters + * a set of converters which can change strings into other + * objects to pass into executable steps + */ + public Steps(ParameterConverters converters) { + this(new StepsConfiguration(converters)); + } - public CandidateStep[] getSteps(Class<?> stepsClass) { - List<CandidateStep> steps = new ArrayList<CandidateStep>(); - for (Method method : stepsClass.getMethods()) { - if (method.isAnnotationPresent(Given.class)) { - createCandidateStep(steps, method, method.getAnnotation(Given.class).value()); - createCandidateStepsFromAliases(steps, method); - } - if (method.isAnnotationPresent(When.class)) { - createCandidateStep(steps, method, method.getAnnotation(When.class).value()); - createCandidateStepsFromAliases(steps, method); - } - if (method.isAnnotationPresent(Then.class)) { - createCandidateStep(steps, method, method.getAnnotation(Then.class).value()); - createCandidateStepsFromAliases(steps, method); - } - } - return steps.toArray(new CandidateStep[steps.size()]); - } + /** + * Creates Steps with all custom dependencies + * + * @param configuration + * the StepsConfiguration + */ + public Steps(StepsConfiguration configuration) { + this.configuration = configuration; + } - void createCandidateStep(List<CandidateStep> steps, Method method, String stepAsString) { - steps.add(new CandidateStep(stepAsString, method, this, configuration.getPatternBuilder(), configuration - .getMonitor(), configuration.getParameterConverters(), configuration.getStartingWords())); - } + public CandidateStep[] getSteps() { + return getSteps(this.getClass()); + } - private void createCandidateStepsFromAliases(List<CandidateStep> steps, + public CandidateStep[] getSteps(Class<?> stepsClass) { + List<CandidateStep> steps = new ArrayList<CandidateStep>(); + for (Method method : stepsClass.getMethods()) { + if (method.isAnnotationPresent(Given.class)) { + String value = method.getAnnotation(Given.class).value(); + createCandidateStep(steps, method, value); + createCandidateStepsFromAliases(steps, method); + } + if (method.isAnnotationPresent(When.class)) { + String value = method.getAnnotation(When.class).value(); + createCandidateStep(steps, method, value); + createCandidateStepsFromAliases(steps, method); + } + if (method.isAnnotationPresent(Then.class)) { + String value = method.getAnnotation(Then.class).value(); + createCandidateStep(steps, method, value); + createCandidateStepsFromAliases(steps, method); + } + } + return steps.toArray(new CandidateStep[steps.size()]); + } + + void createCandidateStep(List<CandidateStep> steps, Method method, + String stepAsString) { + checkForDuplicateCandidateSteps(steps, stepAsString); + steps.add(new CandidateStep(stepAsString, method, this, configuration + .getPatternBuilder(), configuration.getMonitor(), configuration + .getParameterConverters(), configuration.getStartingWords())); + } + + private void checkForDuplicateCandidateSteps(List<CandidateStep> steps, + String stepAsString) { + for (CandidateStep step : steps) { + if (step.getStepAsString().equals(stepAsString)) { + throw new DuplicateCandidateStepFoundException(stepAsString); + } + } + } + + private void createCandidateStepsFromAliases(List<CandidateStep> steps, Method method) { - if ( method.isAnnotationPresent(Aliases.class) ){ - String[] aliases = method.getAnnotation(Aliases.class).values(); - for ( String alias : aliases ){ - createCandidateStep(steps, method, alias); - } - } + if (method.isAnnotationPresent(Aliases.class)) { + String[] aliases = method.getAnnotation(Aliases.class).values(); + for (String alias : aliases) { + createCandidateStep(steps, method, alias); + } + } } public List<Step> runBeforeScenario() { @@ -146,16 +165,21 @@ public List<Step> runAfterScenario() { List<Step> steps = new ArrayList<Step>(); - steps.addAll(stepsHavingOutcome(AfterScenario.class, ANY, new OkayToRun(), new OkayToRun())); - steps.addAll(stepsHavingOutcome(AfterScenario.class, SUCCESS, new OkayToRun(), new DoNotRun())); - steps.addAll(stepsHavingOutcome(AfterScenario.class, FAILURE, new DoNotRun(), new OkayToRun())); + steps.addAll(stepsHavingOutcome(AfterScenario.class, ANY, + new OkayToRun(), new OkayToRun())); + steps.addAll(stepsHavingOutcome(AfterScenario.class, SUCCESS, + new OkayToRun(), new DoNotRun())); + steps.addAll(stepsHavingOutcome(AfterScenario.class, FAILURE, + new DoNotRun(), new OkayToRun())); return steps; } - private List<Step> stepsHaving(final Class<? extends Annotation> annotationClass, final StepPart forScenarios) { + private List<Step> stepsHaving( + final Class<? extends Annotation> annotationClass, + final StepPart forScenarios) { List<Step> steps = new ArrayList<Step>(); - for (final Method method : this.getClass().getMethods()) { - if (method.isAnnotationPresent(annotationClass)) { + for (final Method method : this.getClass().getMethods()) { + if (method.isAnnotationPresent(annotationClass)) { steps.add(new Step() { public StepResult doNotPerform() { return forScenarios.run(annotationClass, method); @@ -164,66 +188,86 @@ public StepResult perform() { return forScenarios.run(annotationClass, method); } - + }); } - } - return steps; + } + return steps; } - - - private List<Step> stepsHavingOutcome(final Class<? extends AfterScenario> annotationClass, final Outcome outcome, final StepPart forSuccessfulScenarios, final StepPart forUnsuccessfulScenarios) { + + private List<Step> stepsHavingOutcome( + final Class<? extends AfterScenario> annotationClass, + final Outcome outcome, final StepPart forSuccessfulScenarios, + final StepPart forUnsuccessfulScenarios) { List<Step> steps = new ArrayList<Step>(); - for (final Method method : this.getClass().getMethods()) { - if (method.isAnnotationPresent(annotationClass) ) { - AfterScenario annotation = method.getAnnotation(annotationClass); - if ( outcome.equals(annotation.uponOutcome()) ){ + for (final Method method : this.getClass().getMethods()) { + if (method.isAnnotationPresent(annotationClass)) { + AfterScenario annotation = method + .getAnnotation(annotationClass); + if (outcome.equals(annotation.uponOutcome())) { steps.add(new Step() { public StepResult doNotPerform() { - return forUnsuccessfulScenarios.run(annotationClass, method); + return forUnsuccessfulScenarios.run( + annotationClass, method); } public StepResult perform() { - return forSuccessfulScenarios.run(annotationClass, method); + return forSuccessfulScenarios.run(annotationClass, + method); } - - }); + + }); } } - } - return steps; + } + return steps; } - + private class OkayToRun implements StepPart { - public StepResult run(final Class<? extends Annotation> annotation, Method method) { + public StepResult run(final Class<? extends Annotation> annotation, + Method method) { try { method.invoke(Steps.this); } catch (InvocationTargetException e) { - if (e.getCause() != null) { throw new BeforeOrAfterScenarioException(annotation, method, e.getCause()); } + if (e.getCause() != null) { + throw new BeforeOrAfterScenarioException(annotation, + method, e.getCause()); + } } catch (Throwable t) { throw new RuntimeException(t); } return new SilentStepResult(); } } - + private class DoNotRun implements StepPart { - public StepResult run(Class<? extends Annotation> annotation, Method method) { + public StepResult run(Class<? extends Annotation> annotation, + Method method) { return new SilentStepResult(); } } - + private interface StepPart { StepResult run(Class<? extends Annotation> annotation, Method method); } - - public class SilentStepResult extends StepResult { - public SilentStepResult() { + + public class SilentStepResult extends StepResult { + public SilentStepResult() { super(""); } - + @Override - public void describeTo(ScenarioReporter reporter) {} + public void describeTo(ScenarioReporter reporter) { + } } + + @SuppressWarnings("serial") + public static class DuplicateCandidateStepFoundException extends RuntimeException { + + public DuplicateCandidateStepFoundException(String message) { + super(message); + } + + } }
To unsubscribe from this list please visit:
