io.cucumber.gherkin.CucumberScenarioLoader Maven / Gradle / Ivy
package io.cucumber.gherkin;
import com.google.common.collect.FluentIterable;
import io.cucumber.core.feature.FeatureParser;
import io.cucumber.core.feature.Options;
import io.cucumber.core.runtime.FeaturePathFeatureSupplier;
import io.cucumber.messages.types.*;
import net.serenitybdd.cucumber.utils.PathUtils;
import net.serenitybdd.cucumber.suiteslicing.TestStatistics;
import net.serenitybdd.cucumber.suiteslicing.WeightedCucumberScenario;
import net.serenitybdd.cucumber.suiteslicing.WeightedCucumberScenarios;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
/**
* Reads cucumber feature files and breaks them down into a collection of scenarios (WeightedCucumberScenarios).
*/
public class CucumberScenarioLoader {
private static final Logger LOGGER = LoggerFactory.getLogger(CucumberScenarioLoader.class);
private final Supplier classLoader = CucumberScenarioLoader.class::getClassLoader;
private final List featurePaths;
private final TestStatistics statistics;
private Map mapsForFeatures = new HashMap<>();
public CucumberScenarioLoader(List featurePaths, TestStatistics statistics) {
this.featurePaths = featurePaths;
this.statistics = statistics;
}
public WeightedCucumberScenarios load() {
LOGGER.debug("Feature paths are {}", featurePaths);
FeatureParser parser = new FeatureParser(UUID::randomUUID);
Options featureOptions = () -> featurePaths;
FeaturePathFeatureSupplier supplier =
new FeaturePathFeatureSupplier(classLoader, featureOptions, parser);
IntStream.range(0, supplier.get().size())
.forEach(i ->
{
io.cucumber.core.gherkin.Feature feature = supplier.get().get(i);
Parser gherkinParser = new Parser<>(new GherkinDocumentBuilder(new IncrementingIdGenerator(),feature.getUri().toString()));
mapsForFeatures.put(gherkinParser.parse(feature.getSource(),feature.getUri().toString()).getFeature().get(),
feature.getUri());
});
List features = new ArrayList<>();
List gherkinFeatures = supplier.get();
for(io.cucumber.core.gherkin.Feature gherkinFeature : gherkinFeatures) {
Parser gherkinParser = new Parser(new GherkinDocumentBuilder(new IncrementingIdGenerator(),gherkinFeature.getUri().toString()));
GherkinDocument gherkinDocument = (GherkinDocument)gherkinParser.parse(gherkinFeature.getSource(),gherkinFeature.getUri().toString());
features.add(gherkinDocument.getFeature().get());
}
List weightedCucumberScenarios = mapsForFeatures.keySet().stream()
.map(getScenarios()).flatMap(List::stream).collect(toList());
return new WeightedCucumberScenarios(weightedCucumberScenarios);
}
private Function> getScenarios() {
return cucumberFeature -> {
try {
return (cucumberFeature == null) ? Collections.emptyList() : cucumberFeature.getChildren()
.stream()
//.filter(child -> asList(ScenarioOutline.class, Scenario.class).contains(child.getClass()))
.filter(child -> child.getScenario() != null && child.getScenario().isPresent())
.map(FeatureChild::getScenario)
.map(scenarioDefinition -> new WeightedCucumberScenario(
PathUtils.getAsFile(mapsForFeatures.get(cucumberFeature)).getName(),
cucumberFeature.getName(),
scenarioDefinition.get().getName(),
scenarioWeightFor(cucumberFeature, scenarioDefinition.get()),
tagsFor(cucumberFeature, scenarioDefinition.get()),
scenarioCountFor(scenarioDefinition.get())))
.collect(toList());
} catch (Throwable e) {
throw new IllegalStateException(String.format("Could not extract scenarios from %s", mapsForFeatures.get(cucumberFeature)), e);
}
};
}
private int scenarioCountFor(Scenario scenarioDefinition) {
if (scenarioDefinition.getExamples().size() > 0) {
return (scenarioDefinition).getExamples().stream().map(examples -> examples.getTableBody().size()).mapToInt(Integer::intValue).sum();
} else {
return 1;
}
}
private Set tagsFor(Feature feature, Scenario scenarioDefinition) {
return FluentIterable.concat(feature.getTags(), scenarioTags(scenarioDefinition)).stream().map(Tag::getName).collect(toSet());
}
private List scenarioTags(Scenario scenario) {
if (scenario.getExamples().isEmpty()) {
return scenario.getTags();
} else {
return Stream.of(scenario.getTags(), scenario.getExamples()
.stream().flatMap(e -> e.getTags().stream()).collect(toList())).flatMap(Collection::stream)
.collect(Collectors.toList());
}
}
private BigDecimal scenarioWeightFor(Feature feature, Scenario scenarioDefinition) {
return statistics.scenarioWeightFor(feature.getName(), scenarioDefinition.getName());
}
private static Envelope readEnvelopeFromPath(Path path) {
try {
byte[] bytes = Files.readAllBytes(path);
String data = new String(bytes, StandardCharsets.UTF_8);
return Envelope.of(new Source(path.toString(), data, SourceMediaType.TEXT_X_CUCUMBER_GHERKIN_PLAIN));
} catch (IOException e) {
throw new GherkinException(e.getMessage(), e);
}
}
}