All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
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.
net.thucydides.cucumber.ThucydidesReporter Maven / Gradle / Ivy
package net.thucydides.cucumber;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import cucumber.runtime.StepDefinitionMatch;
import gherkin.formatter.Formatter;
import gherkin.formatter.Reporter;
import gherkin.formatter.model.*;
import net.thucydides.core.Thucydides;
import net.thucydides.core.ThucydidesListeners;
import net.thucydides.core.ThucydidesReports;
import net.thucydides.core.model.*;
import net.thucydides.core.reports.ReportService;
import net.thucydides.core.requirements.FileSystemRequirementsTagProvider;
import net.thucydides.core.steps.BaseStepListener;
import net.thucydides.core.steps.ExecutedStepDescription;
import net.thucydides.core.steps.StepEventBus;
import net.thucydides.core.steps.StepFailure;
import net.thucydides.core.webdriver.Configuration;
import net.thucydides.core.webdriver.ThucydidesWebDriverSupport;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.lang3.StringUtils;
import org.junit.internal.AssumptionViolatedException;
import java.io.File;
import java.io.IOException;
import java.util.*;
import static ch.lambdaj.Lambda.*;
import static org.apache.commons.lang3.StringUtils.isEmpty;
/**
* Generates Thucydides reports.
*
* @author L.Carausu ([email protected] )
*/
public class ThucydidesReporter implements Formatter, Reporter {
private static final String OPEN_PARAM_CHAR = "\uff5f";
private static final String CLOSE_PARAM_CHAR = "\uff60";
private static final List SKIPPED_TAGS = ImmutableList.of("@skip", "@wip");
private final Queue stepQueue;
private Configuration systemConfiguration;
private ThreadLocal thucydidesListenersThreadLocal;
private final List baseStepListeners;
private Feature currentFeature;
private int currentExample = 0;
private boolean examplesRunning;
private List> exampleRows;
private int exampleCount = 0;
private DataTable table;
private boolean firstStep = true;
private String currentUri;
private static Optional forcedStoryResult = Optional.absent();
private static Optional forcedScenarioResult = Optional.absent();
private void clearStoryResult() {
forcedStoryResult = Optional.absent();
}
private void clearScenarioResult() {
forcedScenarioResult = Optional.absent();
}
private boolean isPendingStory() {
return ((forcedStoryResult.or(TestResult.UNDEFINED) == TestResult.PENDING)
|| (forcedScenarioResult.or(TestResult.UNDEFINED) == TestResult.PENDING));
}
private boolean isSkippedStory() {
return ((forcedStoryResult.or(TestResult.UNDEFINED) == TestResult.SKIPPED)
|| (forcedScenarioResult.or(TestResult.UNDEFINED) == TestResult.SKIPPED));
}
public ThucydidesReporter(Configuration systemConfiguration) {
this.systemConfiguration = systemConfiguration;
this.stepQueue = new LinkedList<>();
thucydidesListenersThreadLocal = new ThreadLocal<>();
baseStepListeners = Lists.newArrayList();
clearStoryResult();
}
protected ThucydidesListeners getThucydidesListeners() {
if (thucydidesListenersThreadLocal.get() == null) {
ThucydidesListeners listeners = ThucydidesReports.setupListeners(systemConfiguration);
thucydidesListenersThreadLocal.set(listeners);
synchronized (baseStepListeners) {
baseStepListeners.add(listeners.getBaseStepListener());
}
}
return thucydidesListenersThreadLocal.get();
}
protected ReportService getReportService() {
return ThucydidesReports.getReportService(systemConfiguration);
}
@Override
public void syntaxError(String state, String event, List legalEvents, String uri, Integer line) {
}
@Override
public void uri(String uri) {
currentUri = uri;
//Cucumber reports only the feature file name but thucydides needs the whole directory structure
//starting from the root path of the features or stories , that's why i have to complete the uri
//currently it works only for features with different names - for more we need a complete uri from cucuber
FileSystemRequirementsTagProvider tagProvider = new FileSystemRequirementsTagProvider();
try {
Optional rootDirectoryPath = tagProvider.getRootDirectoryPath();
if(rootDirectoryPath.isPresent()) {
File rootDirectory = new File(rootDirectoryPath.get());
if (rootDirectory.exists()) {
Collection files = FileUtils.listFiles(rootDirectory, new FeatureFileFilter(uri), TrueFileFilter.INSTANCE);
if (files.size() > 0) {
File firstMatch = files.iterator().next();
currentUri = firstMatch.getAbsolutePath().substring(rootDirectoryPath.get().length() + 1);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class FeatureFileFilter implements IOFileFilter {
private String featureFileName;
public FeatureFileFilter(String featureFileName){
this.featureFileName = featureFileName;
}
@Override
public boolean accept(File file) {
return file.getName().equals(featureFileName);
}
@Override
public boolean accept(File dir, String name) {
return name.equals(featureFileName);
}
}
@Override
public void feature(Feature feature) {
assureTestSuiteFinished();
currentFeature = feature;
configureDriver(feature);
getThucydidesListeners().withDriver(ThucydidesWebDriverSupport.getDriver());
Story userStory = Story.withIdAndPath(feature.getId(), feature.getName(), currentUri).asFeature();
if (!isEmpty(feature.getDescription())) {
userStory = userStory.withNarrative(feature.getDescription());
}
StepEventBus.getEventBus().testSuiteStarted(userStory);
checkForPending(feature);
checkForSkipped(feature);
}
private void checkForPending(Feature feature) {
if (isPending(feature.getTags())) {
forcedStoryResult = Optional.of(TestResult.PENDING);
StepEventBus.getEventBus().suspendTest();
}
}
private void checkForSkipped(Feature feature) {
if (isSkippedOrWIP(feature.getTags())) {
forcedStoryResult = Optional.of(TestResult.SKIPPED);
StepEventBus.getEventBus().suspendTest();
}
}
private void checkForPending(Scenario scenario) {
if (isPending(scenario.getTags())) {
forcedScenarioResult = Optional.of(TestResult.PENDING);
StepEventBus.getEventBus().suspendTest();
}
}
private void checkForSkipped(Scenario scenario) {
if (isSkippedOrWIP(scenario.getTags())) {
forcedScenarioResult = Optional.of(TestResult.SKIPPED);
StepEventBus.getEventBus().suspendTest();
}
}
private boolean isPending(List tags) {
return hasTag("@pending", tags);
}
private boolean isSkippedOrWIP(List tags) {
for (Tag tag : tags) {
if (SKIPPED_TAGS.contains(tag.getName())) {
return true;
}
}
return false;
}
private boolean hasTag(String tagName, List tags) {
for (Tag tag : tags) {
if (tag.getName().equals(tagName)) {
return true;
}
}
return false;
}
private void configureDriver(Feature feature) {
StepEventBus.getEventBus().setUniqueSession(systemConfiguration.getUseUniqueBrowser());
String requestedDriver = getDriverFrom(feature);
if (StringUtils.isNotEmpty(requestedDriver)) {
ThucydidesWebDriverSupport.initialize(requestedDriver);
} else {
ThucydidesWebDriverSupport.initialize();
}
}
private String getDriverFrom(Feature feature) {
List tags = feature.getTags();
String requestedDriver = null;
for (Tag tag : tags) {
if (tag.getName().startsWith("@driver:")) {
requestedDriver = tag.getName().substring(8);
}
}
return requestedDriver;
}
@Override
public void scenarioOutline(ScenarioOutline scenarioOutline) {
}
@Override
public void examples(Examples examples) {
reinitializeExamples();
List examplesTableRows = examples.getRows();
List headers = getHeadersFrom(examplesTableRows);
List> rows = getValuesFrom(examplesTableRows, headers);
for (int i = 1; i < examplesTableRows.size(); i++) {
addRow(exampleRows, headers, examplesTableRows.get(i));
}
table = (table == null) ?
thucydidesTableFrom(headers, rows, examples.getName(), examples.getDescription())
: addTableRowsTo(table, headers, rows, examples.getName(), examples.getDescription());
exampleCount = examples.getRows().size() - 1;// table.getSize();
}
private void reinitializeExamples() {
examplesRunning = true;
currentExample = 0;
exampleRows = new ArrayList<>();
}
private List getHeadersFrom(List examplesTableRows) {
ExamplesTableRow headerRow = examplesTableRows.get(0);
return headerRow.getCells();
}
private List> getValuesFrom(List examplesTableRows, List headers) {
List> rows = Lists.newArrayList();
for (int row = 1; row < examplesTableRows.size(); row++) {
Map rowValues = Maps.newHashMap();
int column = 0;
for (String cellValue : examplesTableRows.get(row).getCells()) {
String columnName = headers.get(column++);
rowValues.put(columnName, cellValue);
}
rows.add(rowValues);
}
return rows;
}
private void addRow(List> exampleRows,
List headers,
ExamplesTableRow currentTableRow) {
Map row = new HashMap<>();
for (int j = 0; j < headers.size(); j++) {
row.put(headers.get(j), currentTableRow.getCells().get(j));
}
exampleRows.add(row);
}
private DataTable thucydidesTableFrom(List headers,
List> rows,
String name,
String description) {
return DataTable.withHeaders(headers).andMappedRows(rows).andTitle(name).andDescription(description).build();
}
private DataTable addTableRowsTo(DataTable table, List headers,
List> rows,
String name,
String description) {
table.startNewDataSet(name, description);
for (Map row : rows) {
table.addRow(rowValuesFrom(headers, row));
}
return table;
}
private Map rowValuesFrom(List headers, Map row) {
Map rowValues = Maps.newHashMap();
for (String header : headers) {
rowValues.put(header, row.get(header));
}
return ImmutableMap.copyOf(rowValues);
}
@Override
public void startOfScenarioLifeCycle(Scenario scenario) {
if (examplesRunning) {
if (firstStep) {
startScenario(scenario);
StepEventBus.getEventBus().useExamplesFrom(table);
firstStep = false;
}
startExample();
} else {
startScenario(scenario);
}
}
private void startScenario(Scenario scenario) {
StepEventBus.getEventBus().testStarted(scenario.getName());
StepEventBus.getEventBus().addDescriptionToCurrentTest(scenario.getDescription());
StepEventBus.getEventBus().addTagsToCurrentTest(convertCucumberTags(currentFeature.getTags()));
StepEventBus.getEventBus().addTagsToCurrentTest(convertCucumberTags(scenario.getTags()));
getThucydidesListeners().withDriver(ThucydidesWebDriverSupport.getDriver());
}
private List convertCucumberTags(List cucumberTags) {
List tags = Lists.newArrayList();
for (Tag tag : cucumberTags) {
tags.add(TestTag.withValue(tag.getName().substring(1)));
}
return ImmutableList.copyOf(tags);
}
@Override
public void endOfScenarioLifeCycle(Scenario scenario) {
if (examplesRunning) {
finishExample();
} else {
generateReports();
}
}
private void startExample() {
Map data = exampleRows.get(currentExample);
StepEventBus.getEventBus().clearStepFailures();
StepEventBus.getEventBus().exampleStarted(data);
currentExample++;
}
private void finishExample() {
StepEventBus.getEventBus().exampleFinished();
exampleCount--;
if (exampleCount == 0) {
examplesRunning = false;
generateReports();
}
}
@Override
public void background(Background background) {
StepEventBus.getEventBus().setBackgroundDescription(background.getDescription());
}
@Override
public void scenario(Scenario scenario) {
clearScenarioResult();
checkForPending(scenario);
checkForSkipped(scenario);
}
@Override
public void step(Step step) {
stepQueue.add(step);
}
@Override
public void done() {
assureTestSuiteFinished();
}
@Override
public void close() {
assureTestSuiteFinished();
}
private void assureTestSuiteFinished() {
if (currentFeature != null) {
stepQueue.clear();
StepEventBus.getEventBus().testSuiteFinished();
StepEventBus.getEventBus().clear();
Thucydides.done();
table = null;
firstStep = true;
}
}
@Override
public void eof() {
}
@Override
public void before(Match match, Result result) {
}
@Override
public void result(Result result) {
Step currentStep = stepQueue.poll();
if (Result.PASSED.equals(result.getStatus())) {
StepEventBus.getEventBus().stepFinished();
} else if (Result.FAILED.equals(result.getStatus())) {
failed(stepTitleFrom(currentStep), result.getError());
} else if (Result.SKIPPED.equals(result)) {
StepEventBus.getEventBus().stepIgnored();
} else if (Result.UNDEFINED.equals(result)) {
StepEventBus.getEventBus().stepStarted(ExecutedStepDescription.withTitle(stepTitleFrom(currentStep)));
StepEventBus.getEventBus().stepPending();
}
if (stepQueue.isEmpty()) {
if (examplesRunning) { //finish enclosing step because testFinished resets the queue
StepEventBus.getEventBus().stepFinished();
}
updatePendingResults();
updateSkippedResults();
StepEventBus.getEventBus().testFinished();
}
}
private void updatePendingResults() {
if (isPendingStory()) {
StepEventBus.getEventBus().setAllStepsTo(TestResult.PENDING);
}
}
private void updateSkippedResults() {
if (isSkippedStory()) {
StepEventBus.getEventBus().setAllStepsTo(TestResult.SKIPPED);
}
}
public void failed(String stepTitle, Throwable cause) {
Throwable rootCause = cause.getCause() != null ? cause.getCause() : cause;
StepEventBus.getEventBus().updateCurrentStepTitle(stepTitle);
if (isAssumptionFailure(rootCause)) {
StepEventBus.getEventBus().assumptionViolated(rootCause.getMessage());
} else {
StepEventBus.getEventBus().stepFailed(new StepFailure(ExecutedStepDescription.withTitle(normalized(stepTitle)), rootCause));
}
}
private boolean isAssumptionFailure(Throwable rootCause) {
return (AssumptionViolatedException.class.isAssignableFrom(rootCause.getClass()));
}
@Override
public void after(Match match, Result result) {
}
@Override
public void match(Match match) {
if (match instanceof StepDefinitionMatch) {
Step currentStep = stepQueue.peek();
String stepTitle = stepTitleFrom(currentStep);
StepEventBus.getEventBus().stepStarted(ExecutedStepDescription.withTitle(stepTitle));
StepEventBus.getEventBus().updateCurrentStepTitle(normalized(stepTitle));
}
}
private String stepTitleFrom(Step currentStep) {
return currentStep.getKeyword() + currentStep.getName();
}
@Override
public void embedding(String mimeType, byte[] data) {
}
@Override
public void write(String text) {
}
private synchronized void generateReports() {
getReportService().generateReportsFor(getAllTestOutcomes());
}
public List getAllTestOutcomes() {
return flatten(extract(baseStepListeners, on(BaseStepListener.class).getTestOutcomes()));
}
private String normalized(String value) {
return value.replaceAll(OPEN_PARAM_CHAR, "{").replaceAll(CLOSE_PARAM_CHAR, "}");
}
}