public void processStep(StepToken step) { ChorusContext c = ChorusContext.getContext(); String action = step.getAction(); Matcher m = p.matcher(action); List<String> variables = new LinkedList<>(); while(m.find()) { variables.add(m.group()); } if (!variables.isEmpty()) { replaceVariables(c, action, m, variables, step); } }
private boolean doProcessStep(StepToken stepToken, List<StepMacro> macros, int depth, boolean alreadyMatched) { boolean result = false; if ( depth > MAX_STEP_DEPTH ) { throw new RecursiveStepMacroException("Maximum Step Depth (" + MAX_STEP_DEPTH + ") was reached when processing step " + stepToken.toString() + " are your StepMacro: infinitely recursive?"); } Matcher macroMatcher = pattern.matcher(stepToken.getAction()); if ( macroMatcher.matches() ) { if (! alreadyMatched) { //sometimes we are just matching, looking for duplicate matches log.debug(stepToken.getAction() + " matches StepMacro: " + pattern + ", will add " + steps.size() + " child steps"); addChildSteps(stepToken, macroMatcher, macros, depth); } else { log.debug(stepToken.getAction() + " matches StepMacro: " + pattern); log.warn("Duplicate StepMacro: match for step " + stepToken.getAction() + pattern + ", Chorus will use the steps from the first match"); } result = true; } return result; }
private ScenarioToken createScenarioFromOutline(String scenarioName, ScenarioToken outlineScenario, List<String> placeholders, List<String> values,List<String> currentFeaturesTags, List<String> currentScenariosTags, List<StepMacro> stepMacros) { ScenarioToken scenario = new ScenarioToken(); List<String> outlineVariableTags = findChorusTagsFromOutlineVariables(placeholders, values); //append the first paramter to the scenario name if there is one String firstParam = " " + (!values.isEmpty() ? values.get(0) : ""); scenarioName += firstParam.trim().length() > 0 ? firstParam : ""; scenario.setName(scenarioName); //then the outline scenario steps for (StepToken step : outlineScenario.getSteps()) { String action = step.getAction(); for (int i = 0; i < placeholders.size(); i++) { String placeholder = placeholders.get(i); String value = values.get(i); value = RegexpUtils.escapeRegexReplacement(value); action = action.replaceAll("<" + placeholder + ">", value); } addStepToScenario(scenario, createStepToken(step.getType(), action), stepMacros); } //add the filter tags scenario.addTags(currentFeaturesTags); scenario.addTags(currentScenariosTags); scenario.addTags(outlineVariableTags); return scenario; }
private void addChildSteps(StepToken parentToken, Matcher macroMatcher, List<StepMacro> macros, int depth) { for (StepToken s : steps) { String action = s.getAction(); String type = s.getType(); action = replaceVariablesInMacroStep(macroMatcher, action); action = replaceGroupsInMacroStep(macroMatcher, action); //having replaced any capture groups, create the child step StepToken childToken = StepToken.createStep(type, action); //match the new child step against the list of StepMacros recursively boolean alreadyMatched = false; for ( StepMacro stepMacro : macros) { alreadyMatched = stepMacro.doProcessStep(childToken, macros, depth + 1, alreadyMatched); } parentToken.addChildStep(childToken); } }
@Test public void testStepMacroPatternMatch() { StepMacro stepMacro = new StepMacro("I reference a step macro with (\\d+) steps and (\\d+) capture groups"); stepMacro.addStep(StepToken.createStep("Given", "my number of steps is <$1> steps")); stepMacro.addStep(StepToken.createStep("Then", "my number of groups is <$2> groups")); StepToken scenarioStepToken = StepToken.createStep("Given", "I reference a step macro with 2 steps and 2 capture groups"); stepMacro.processStep(scenarioStepToken, Collections.singletonList(stepMacro), false); assertEquals(scenarioStepToken.getChildSteps().size(), 2); assertEquals("my number of steps is 2 steps", scenarioStepToken.getChildSteps().get(0).getAction()); assertEquals("my number of groups is 2 groups", scenarioStepToken.getChildSteps().get(1).getAction()); }
@Test //test that a steps from a step macro themselves matched to the list of step macros recursively, creating //a tree structure of steps //any capture groups in the step macro steps should be expanded before this matching occurs public void testRecursiveMatching() { StepMacro stepMacro = new StepMacro("I have a parent (.*) macro"); stepMacro.addStep(StepToken.createStep("", "With a step which matches a child <$1> macro")); StepMacro childStepMacro = new StepMacro("With a step which matches a child step macro"); childStepMacro.addStep(StepToken.createStep("", "Child Step")); StepToken scenarioStepToken = StepToken.createStep("Given", "I have a parent step macro"); stepMacro.processStep(scenarioStepToken, Arrays.asList(stepMacro, childStepMacro), false); assertEquals(scenarioStepToken.getChildSteps().size(), 1); assertEquals("With a step which matches a child step macro", scenarioStepToken.getChildSteps().get(0).getAction()); assertEquals(scenarioStepToken.getChildSteps().get(0).getChildSteps().size(), 1); assertEquals("Child Step", scenarioStepToken.getChildSteps().get(0).getChildSteps().get(0).getAction()); }
@Override public StepTokenBean marshal(StepToken v) throws Exception { StepTokenBean toRet = new StepTokenBean(); toRet.setTokenId(v.getTokenId()); toRet.setType(v.getType()); toRet.setAction(v.getAction()); toRet.setEndState(v.getEndState()); toRet.setMessage(v.getMessage()); //we don't want to add an error details attribute unless there's a real value if ( ! "".equals(v.getErrorDetails().trim())) { toRet.setErrorDetails(v.getErrorDetails()); } if (v.getException()!=null){ toRet.setException(v.getException()); toRet.setStackTrace(v.getStackTrace()); } toRet.setTimeTaken(v.getTimeTaken()); toRet.setTimeTakenSeconds(FormattingUtils.getTimeTakenAsSecondsString(v.getTimeTaken())); toRet.setChildSteps(v.getChildSteps()); return toRet; }
StepMatcher stepMatcher = new StepMatcher(stepInvokers, step.getAction()); stepMatcher.findStepMethod();