
io.github.martinschneider.cucumber2junit.FeatureParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cucumber2junit-maven-plugin Show documentation
Show all versions of cucumber2junit-maven-plugin Show documentation
Generates plain JUnit tests from Gherkin feature files. This is useful when you want to execute Cucumber tests in an environment which does not allow custom JUnit runners, e.g. the AWS Device Farm.
The newest version!
package io.github.martinschneider.cucumber2junit;
import io.github.martinschneider.cucumber2junit.model.Feature;
import io.github.martinschneider.cucumber2junit.model.Scenario;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Parser for feature files. */
public class FeatureParser {
private static final Logger LOG = LoggerFactory.getLogger(FeatureParser.class);
/**
* Parse features from a given directory. Only scenarios which have at least one of the specified
* tags will be included. Scenarios "inherit" the tags of the feature they are defined in.
*
* @param path directory containing the feature files
* @param tags {@link List} of tags to include
* @return {@link List} of {@link Feature}s
*/
public List parseFeatures(String path, String... tags) {
List features = new ArrayList();
LOG.info("Recursively parsing feature files from {}", path);
try (Stream paths = Files.walk(Paths.get(path))) {
paths
.filter(Files::isRegularFile)
.forEach(x -> parseFeature(x, Paths.get(path), features, tags));
} catch (IOException e) {
LOG.error("Couldn't load feature files from directory {}", path);
}
return features;
}
private List parseFeature(
Path path, Path rootPath, List features, String... tags) {
LOG.info("Processing feature file {}", path);
try (BufferedReader reader = new BufferedReader(new FileReader(path.toFile()))) {
List scenarios = new ArrayList();
List featureTags = new ArrayList();
List includedTags = parseRequiredTags(tags).getLeft();
List excludedTags = parseRequiredTags(tags).getRight();
String featureName = "";
String line = "";
String previousLine = "";
int lineNumber = 1;
LOG.info("Required tags: {}, forbidden tags: {}", includedTags, excludedTags);
while ((line = reader.readLine()) != null) {
if (line.trim().startsWith("Feature")) {
featureTags = parseTags(previousLine);
featureName = parseFeatureName(line);
}
if (line.trim().startsWith("Scenario")) {
Scenario scenario = parseScenario(line, previousLine, lineNumber);
List allTags = new ArrayList(featureTags);
allTags.addAll(scenario.getTags());
if (includedTags.stream().allMatch(allTags::contains)
&& excludedTags.stream().noneMatch(allTags::contains)) {
LOG.info("Adding scenario {} with tags {}", scenario, allTags);
scenarios.add(scenario);
} else {
LOG.debug("Skipping scenario {}", scenario);
}
}
previousLine = line;
lineNumber++;
}
if (!scenarios.isEmpty()) {
features.add(
new Feature(featureName, rootPath.relativize(path).toString(), scenarios, featureTags));
}
if (scenarios.size() == 1) {
LOG.info("1 matching scenario added");
} else {
LOG.info("{} matching scenarios added", scenarios.size());
}
} catch (IOException e) {
LOG.warn("Error reading feature file {}. Skipping!");
}
return features;
}
// the left side of the Pair includes the required tags, the right side the forbidden ones
private Pair, List> parseRequiredTags(String[] input) {
List requiredTags = new ArrayList();
List forbiddenTags = new ArrayList();
Pair, List> tags = Pair.of(requiredTags, forbiddenTags);
for (String tag : input) {
if (tag.startsWith("~")) {
forbiddenTags.add(tag.substring(1));
} else {
requiredTags.add(tag);
}
}
return tags;
}
static String parseFeatureName(String line) {
return line.replaceAll("Feature: ", "").trim();
}
static String parseScenarioName(String line) {
return line.replaceAll("Scenario( Outline)?: ", "").trim();
}
static Scenario parseScenario(String line, String previousLine, int lineNumber) {
return new Scenario(lineNumber, parseScenarioName(line), parseTags(previousLine));
}
static List parseTags(String line) {
List tags = new ArrayList();
if (line.isEmpty()) {
return Collections.emptyList();
} else {
String[] tagsArray = line.trim().replaceAll(" +", " ").split(" ");
for (String tag : tagsArray) {
if (!tag.isEmpty()) {
tags.add(tag.trim().replaceAll("@", ""));
}
}
return tags;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy