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); } }
public boolean inOneOf(StepEndState... states) { boolean result = false; for ( StepEndState s : states) { if ( s == getEndState()) { result = true; break; } } return result; }
/** * May be overridden (e.g. to add control codes for colouring terminal output) */ protected String getMessage(StepToken step) { return step.getMessage(); }
/** * If this is a leaf step, total count will be 1 * If this step is a step macro, total count will equal the number of (direct or indirect) leaf step descendants * * @return the total number of steps represented by this StepToken */ public int getTotalStepCountWithDescendants() { int descendantCount = isStepMacro() ? 0 : 1; for ( StepToken c : childSteps) { descendantCount += c.getTotalStepCountWithDescendants(); } return descendantCount; }
public EndState getEndState() { EndState result = EndState.PASSED; for ( StepToken s : steps) { //steps may all be skipped if a feature start scenario failed - the subsequent scenario should all fail if ( s.inOneOf(FAILED, UNDEFINED, TIMEOUT, NOT_RUN, SKIPPED) ) { result = EndState.FAILED; break; } else if ( s.getEndState() == StepEndState.PENDING ) { result = EndState.PENDING; break; } } return result; }
@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; }
@Override public StepToken unmarshal(StepTokenBean v) throws Exception { StepToken stepToken = StepToken.createStep(v.getType(), v.getAction()); stepToken.setEndState(v.getEndState()); stepToken.setMessage(v.getMessage()); stepToken.setException(v.getException()); stepToken.setStackTrace(v.getStackTrace()); stepToken.setTimeTaken(v.getTimeTaken()); if ( v.getErrorDetails() != null ) { stepToken.setErrorDetails(v.getErrorDetails()); } for ( StepToken c : v.getChildSteps()) { stepToken.addChildStep(c); } return stepToken; }
@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()); }
private void createFeatureOne() { ScenarioToken scenarioToken = new ScenarioToken(); scenarioToken.setName("Test Scenario"); StepToken stepOne = scenarioToken.addStep(StepToken.createStep("If", "I create a step")); stepOne.setEndState(StepEndState.PASSED); StepToken stepTwo = scenarioToken.addStep(StepToken.createStep("If", "I create a second step")); stepTwo.setEndState(StepEndState.FAILED); StepToken stepChild = StepToken.createStep("If", "I create a step macro child step"); stepChild.setEndState(StepEndState.FAILED); stepTwo.addChildStep(stepChild); StepToken stepGrandchild = StepToken.createStep("If", "I create a step grandchild"); stepGrandchild.setEndState(StepEndState.FAILED); stepGrandchild.setMessage("Failed due to a horrific and unforseen cataclysm"); stepChild.addChildStep(stepGrandchild); StepToken peerStep = StepToken.createStep("If", "I create a peer step which was skipped"); peerStep.setEndState(StepEndState.SKIPPED); stepChild.addChildStep(peerStep); FeatureToken featureToken = new FeatureToken(); featureToken.setName("Feature One"); featureToken.addScenario(scenarioToken); listOfFeatures.add(featureToken); }
private void createFeatureThree() { ScenarioToken scenarioThree = new ScenarioToken(); scenarioThree.setName("Scenario Three"); StepToken stepSix = scenarioThree.addStep(StepToken.createStep("If", "I add a step to scenario 3")); stepSix.setEndState(StepEndState.TIMEOUT); StepToken stepSeven = scenarioThree.addStep(StepToken.createStep("If", "I add another skipped step to scenario 3")); stepSeven.setEndState(StepEndState.SKIPPED); FeatureToken featureThree = new FeatureToken(); featureThree.setName("Feature Three"); featureThree.addScenario(scenarioThree); listOfFeatures.add(featureThree); }
/** * @param stepInvokerProvider container for StepInvoker to run the steps * @param step details of the step to be executed * @param stepCatalogue *@param skip is true the step will be skipped if found @return the exit state of the executed step */ private StepEndState processStep(ExecutionToken executionToken, StepInvokerProvider stepInvokerProvider, StepToken step, StepCatalogue stepCatalogue, boolean skip) { log.trace("Starting to process step " + (step.isStepMacro() ? "macro " : "") + step); executionListenerSupport.notifyStepStarted(executionToken, step); StepEndState endState; if ( step.isStepMacro() ) { endState = runSteps(executionToken, stepInvokerProvider, step.getChildSteps(), stepCatalogue, skip); } else { endState = processHandlerStep(executionToken, stepInvokerProvider, step, stepCatalogue, skip); } step.setEndState(endState); executionListenerSupport.notifyStepCompleted(executionToken, step); return endState; }
protected StepToken createStepToken(String type, String action) { return StepToken.createStep(type, action); }
@Before public void doBefore() { scenarioToken = new ScenarioToken(); scenarioToken.setName("Test Scenario"); stepOne = scenarioToken.addStep(StepToken.createStep("If", "I create a step")); stepTwo = scenarioToken.addStep(StepToken.createStep("If", "I create a second step")); stepThree = StepToken.createStep("If", "I create a step macro child step"); stepTwo.addChildStep(stepThree); scenarioTwo = new ScenarioToken(); stepFour = scenarioTwo.addStep(StepToken.createStep("If", "I add a step to scenario 2")); featureToken = new FeatureToken(); featureToken.addScenario(scenarioToken); featureToken.addScenario(scenarioTwo); featureTwo = new FeatureToken(); executionToken = new ExecutionToken("My test suite name"); testSuite = new TestSuite(executionToken, Arrays.asList(featureToken, featureTwo)); }
step.setMessage(result.toString()); log.debug("Stored lastResult into ChorusContext with the value " + step.getMessage()); } finally { long executionTime = System.currentTimeMillis() - startTime; step.setTimeTaken(executionTime); if ( foundStepInvoker != null) { stepCatalogue.addExecutedStep(foundStepInvoker, executionTime, StepEndState.PASSED == endState);
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 StepEndState handleGenericException(ExecutionToken executionToken, StepToken step, Throwable cause) { StepEndState endState; step.setThrowable(cause); String causeMessage = cause.getMessage(); causeMessage = causeMessage == null ? "" : causeMessage; log.debug("Step failed due to exception " + cause); String errorDetails = getErrorDetails(cause); step.setMessage(causeMessage); step.setErrorDetails(errorDetails); endState = StepEndState.FAILED; executionToken.incrementStepsFailed(); return endState; }
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 StepEndState handleInterruptedException(ExecutionToken executionToken, StepToken step, Throwable cause) { StepEndState endState; if ( interruptingOnTimeout ) { log.warn("Interrupted during step processing, will TIMEOUT remaining steps"); interruptingOnTimeout = false; endState = StepEndState.TIMEOUT; } else { log.warn("Interrupted during step processing but this was not due to TIMEOUT, will fail step"); endState = StepEndState.FAILED; } executionToken.incrementStepsFailed(); step.setMessage("Interrupted"); step.setErrorDetails(getErrorDetails(cause)); Thread.currentThread().isInterrupted(); //clear the interrupted status return endState; }
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); } }
public void printStepStart(StepToken step, int depth) { StringBuilder depthPadding = getDepthPadding(depth); int stepLengthChars = getStepLengthCharCount() - depthPadding.length(); String terminator = step.isStepMacro() ? "%n" : "|\r"; printStepWithoutEndState(step, depthPadding, stepLengthChars, terminator); if ( ! step.isStepMacro()) { StepProgressRunnable progress = new ShowStepProgressConsoleTask(depthPadding, stepLengthChars, step); startProgressTask(progress, PROGRESS_CURSOR_FRAME_RATE); } }