Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright Technophobia Ltd 2012
*
* This file is part of Substeps.
*
* Substeps is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Substeps is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Substeps. If not, see .
*/
package com.technophobia.substeps.runner;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.technophobia.substeps.execution.ExecutionNode;
import com.technophobia.substeps.execution.Feature;
import com.technophobia.substeps.model.ExampleParameter;
import com.technophobia.substeps.model.FeatureFile;
import com.technophobia.substeps.model.ParentStep;
import com.technophobia.substeps.model.PatternMap;
import com.technophobia.substeps.model.Scenario;
import com.technophobia.substeps.model.Step;
import com.technophobia.substeps.model.StepImplementation;
import com.technophobia.substeps.model.SubSteps.StepParameter;
import com.technophobia.substeps.model.Util;
import com.technophobia.substeps.model.exception.SubstepsConfigurationException;
import com.technophobia.substeps.model.parameter.Converter;
/**
* @author ian
*
*/
public class ExecutionNodeTreeBuilder {
private final Logger log = LoggerFactory.getLogger(ExecutionNodeTreeBuilder.class);
private final TestParameters parameters;
public ExecutionNodeTreeBuilder(final TestParameters parameters) {
this.parameters = parameters;
}
public ExecutionNode buildExecutionNodeTree() {
final ExecutionNode theRootNode = new ExecutionNode();
for (final FeatureFile ff : parameters.getFeatureFileList()) {
buildExecutionNodesForFeature(ff, theRootNode);
}
return theRootNode;
}
/**
* @param notifier
* @param ff
*/
private void buildExecutionNodesForFeature(final FeatureFile ff, final ExecutionNode rootNode) {
if (parameters.isRunnable(ff)) {
final Feature feature = new Feature(ff.getName(), ff.getSourceFile().getName());
final ExecutionNode featureNode = new ExecutionNode();
featureNode.setFileUri(ff.getSourceFile().getAbsolutePath());
// The start of the file seems an appropriate place.
featureNode.setLineNumber(0);
rootNode.addChild(featureNode);
featureNode.setFeature(feature);
featureNode.setTags(ff.getTags());
for (final Scenario sc : ff.getScenarios()) {
buildExectionNodeForScenario(sc, featureNode);
}
} else {
log.debug("feature not runnable: " + ff.toString());
}
}
// TODO - to turn off - @SuppressWarnings("PMD.AvoidCatchingThrowable")
private void buildExectionNodeForScenario(final Scenario scenario, final ExecutionNode featureNode) {
if (scenario != null) {
if (parameters.isRunnable(scenario)) {
final ExecutionNode scenarioNode = new ExecutionNode();
featureNode.addChild(scenarioNode);
scenarioNode.setScenarioName(scenario.getDescription());
scenarioNode.setTags(scenario.getTags());
try {
if (scenario.isOutline()) {
log.debug("building scenario outline tree");
int idx = 0;
for (final ExampleParameter outlineParameters : scenario.getExampleParameters()) {
// invoke the scenario with these parameters as a
// context
final ExecutionNode scenarioOutlineNode = new ExecutionNode();
scenarioNode.addChild(scenarioOutlineNode);
scenarioNode.setOutline(true);
scenarioOutlineNode.setRowNumber(idx);
buildExectionNodeForScenario(scenario, outlineParameters, scenarioOutlineNode);
idx++;
}
}
else {
buildExectionNodeForScenario(scenario, null, scenarioNode);
}
} catch (final Throwable t) {
// something has gone wrong parsing this scenario, no point
// running it so mark it as failed now
scenarioNode.getResult().setFailedToParse(t);
if (parameters.isFailParseErrorsImmediately()) {
throw new SubstepsConfigurationException(t);
}
}
} else {
log.debug("scenario not runnable: " + scenario.toString());
}
}
}
public void buildExectionNodeForScenario(final Scenario scenario, final ExampleParameter scenarioParameters,
final ExecutionNode scenarioNode) {
if (scenario.hasBackground()) {
log.debug("building scenario background steps");
processListOfSteps(scenario.getBackground().getSteps(), parameters.getSyntax().getSubStepsMap(), null,
false, scenarioParameters, scenarioNode);
}
if (scenario.getSteps() != null && !scenario.getSteps().isEmpty()) {
log.debug("processing scenario: [" + scenario.getDescription() + "] steps");
processListOfSteps(scenario.getSteps(), parameters.getSyntax().getSubStepsMap(), null, true,
scenarioParameters, scenarioNode);
}
}
private void processListOfSteps(final List steps, final PatternMap subStepsMapLocal,
final ParentStep parent, final boolean nonBackground, final ExampleParameter parametersForSteps,
final ExecutionNode scenarioNode) {
if (steps == null || steps.isEmpty()) {
throw new SubstepsConfigurationException("Scenario: " + scenarioNode.getDebugStringForThisNode()
+ " has no steps");
}
for (final Step step : steps) {
substituteStepParameters(parametersForSteps, step);
final ExecutionNode stepNode = new ExecutionNode();
if (nonBackground) {
scenarioNode.addChild(stepNode);
// ie 'real'
} else {
// ie background
scenarioNode.addBackground(stepNode);
}
// is this step defined as a root of some sub steps, ie a parent?
ParentStep substepsParent = null;
if (subStepsMapLocal != null) {
substepsParent = locateSubStepsParent(subStepsMapLocal, step);
}
if (substepsParent != null) {
// these are the child steps we want to execute
substepsParent.initialiseParamValues(-1, step.getParameterLine());
final ExampleParameter parametersForSubSteps = substepsParent.getParamValueMap();
stepNode.setLine(substepsParent.getParent().getParameterLine());
stepNode.setFileUri(substepsParent.getSubStepFileUri());
stepNode.setLineNumber(substepsParent.getSourceLineNumber());
final List list = parameters.getSyntax().checkForStepImplementations(
step.getKeyword(), step.getParameterLine());
if (list != null && !list.isEmpty()) {
final StepImplementation problem = list.get(0);
// we've got a step implementation that matches a parent
// step, ie a step that has substeps
// fail immediately or mark as parse error
final String msg = "line: [" + step.getParameterLine() + "] in [" + step.getSource()
+ "] matches step implementation method: [" + problem.getMethod().toString()
+ "] AND matches a sub step definition: [" + substepsParent.getParent().getParameterLine()
+ "] in [" + substepsParent.getSubStepFile() + "]";
throw new SubstepsConfigurationException(msg);
}
processListOfSteps(substepsParent.getSteps(), subStepsMapLocal, substepsParent, nonBackground,
parametersForSubSteps, stepNode);
} else {
executeStep(parent, nonBackground, step, stepNode);
}
}
}
/**
* @param subStepsMapLocal
* @param step
* @return
*/
private ParentStep locateSubStepsParent(final PatternMap subStepsMapLocal, final Step step) {
ParentStep substepsParent = subStepsMapLocal.get(step.getLine(), 0);
// if we're not strict then we can look for other step defs that fit
if (!parameters.getSyntax().isStrict() && substepsParent == null) {
final String originalKeyword = step.getKeyword();
for (final String altKeyword : parameters.getSyntax().getNonStrictKeywordPrecedence()) {
// don't use the same keyword again
if (altKeyword.compareToIgnoreCase(originalKeyword) != 0) {
final String altLine = step.getLine().replaceFirst(originalKeyword, altKeyword);
substepsParent = subStepsMapLocal.get(altLine, 0);
if (substepsParent != null) {
// do we need to modify the parent ??
substepsParent = substepsParent.cloneWithAltLine(altLine);
break;
}
}
}
}
return substepsParent;
}
public void substituteStepParameters(final ExampleParameter parametersForSteps, final Step step) {
// if this is an outline, need to perform token replacement at this
// level before passing down the chain
if (parametersForSteps != null && !parametersForSteps.getParameters().isEmpty()) {
// replace any tokens in this step
step.setParameterLine(substitutePlaceholders(step.getLine(), parametersForSteps.getParameters()));
final List