diff --git a/.github/workflows/test-java.yml b/.github/workflows/test-java.yml index d5536a74dc..3c67b195b9 100644 --- a/.github/workflows/test-java.yml +++ b/.github/workflows/test-java.yml @@ -17,6 +17,7 @@ on: jobs: build: strategy: + fail-fast: true matrix: os: [ ubuntu-latest, windows-latest ] version: [ 17, 21 ] diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b4b4f6014..91fb56e548 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Fixed +- [JUnit Platform Engine] Use `FileSource.withPosition` ([#3084](https://github.com/cucumber/cucumber-jvm/pull/3084) M.P. Korstanje) + ### Changed - [JUnit Platform Engine] Use JUnit Platform 1.14.0 (JUnit Jupiter 5.14.0) diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberDiscoverySelectors.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberDiscoverySelectors.java index ba5efe361c..65883542be 100644 --- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberDiscoverySelectors.java +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberDiscoverySelectors.java @@ -1,7 +1,6 @@ package io.cucumber.junit.platform.engine; import io.cucumber.core.feature.FeatureWithLines; -import io.cucumber.core.gherkin.Feature; import io.cucumber.plugin.event.Node; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoveryIssue; @@ -44,7 +43,7 @@ static FeatureWithLinesSelector from(FeatureWithLines featureWithLines) { static Set from(UniqueId uniqueId) { return uniqueId.getSegments() .stream() - .filter(FeatureOrigin::isFeatureSegment) + .filter(CucumberTestDescriptor::isFeatureSegment) .map(featureSegment -> { URI uri = URI.create(featureSegment.getValue()); Set filePosition = getFilePosition(uniqueId.getLastSegment()); @@ -69,7 +68,7 @@ private static URI stripQuery(URI uri) { } private static Set getFilePosition(UniqueId.Segment segment) { - if (FeatureOrigin.isFeatureSegment(segment)) { + if (CucumberTestDescriptor.isFeatureSegment(segment)) { return Collections.emptySet(); } @@ -111,28 +110,28 @@ public String toString() { static class FeatureElementSelector implements DiscoverySelector { - private final Feature feature; + private final FeatureWithSource feature; private final Node element; - private FeatureElementSelector(Feature feature) { - this(feature, feature); + private FeatureElementSelector(FeatureWithSource feature) { + this(feature, feature.getFeature()); } - private FeatureElementSelector(Feature feature, Node element) { + private FeatureElementSelector(FeatureWithSource feature, Node element) { this.feature = requireNonNull(feature); this.element = requireNonNull(element); } - static FeatureElementSelector selectFeature(Feature feature) { + static FeatureElementSelector selectFeature(FeatureWithSource feature) { return new FeatureElementSelector(feature); } - static FeatureElementSelector selectElement(Feature feature, Node element) { + static FeatureElementSelector selectElement(FeatureWithSource feature, Node element) { return new FeatureElementSelector(feature, element); } static Stream selectElementsAt( - Feature feature, Supplier>> filePositions, + FeatureWithSource feature, Supplier>> filePositions, DiscoveryIssueReporter issueReporter ) { return filePositions.get() @@ -141,13 +140,14 @@ static Stream selectElementsAt( } private static Stream selectElementsAt( - Feature feature, Set filePositions, DiscoveryIssueReporter issueReporter + FeatureWithSource feature, Set filePositions, DiscoveryIssueReporter issueReporter ) { return filePositions.stream().map(filePosition -> selectElementAt(feature, filePosition, issueReporter)); } static FeatureElementSelector selectElementAt( - Feature feature, Supplier> filePosition, DiscoveryIssueReporter issueReporter + FeatureWithSource feature, Supplier> filePosition, + DiscoveryIssueReporter issueReporter ) { return filePosition.get() .map(position -> selectElementAt(feature, position, issueReporter)) @@ -155,9 +155,10 @@ static FeatureElementSelector selectElementAt( } static FeatureElementSelector selectElementAt( - Feature feature, FilePosition filePosition, DiscoveryIssueReporter issueReporter + FeatureWithSource feature, FilePosition filePosition, DiscoveryIssueReporter issueReporter ) { - return feature.findPathTo(candidate -> candidate.getLocation().getLine() == filePosition.getLine()) + return feature.getFeature() + .findPathTo(candidate -> candidate.getLocation().getLine() == filePosition.getLine()) .map(nodes -> nodes.get(nodes.size() - 1)) .map(node -> new FeatureElementSelector(feature, node)) .orElseGet(() -> { @@ -167,7 +168,7 @@ static FeatureElementSelector selectElementAt( } private static void reportInvalidFilePosition( - Feature feature, FilePosition filePosition, DiscoveryIssueReporter issueReporter + FeatureWithSource feature, FilePosition filePosition, DiscoveryIssueReporter issueReporter ) { issueReporter.reportIssue(DiscoveryIssue.create(WARNING, "Feature file " + feature.getUri() @@ -176,7 +177,7 @@ private static void reportInvalidFilePosition( ". Selecting the whole feature instead")); } - static Set selectElementsOf(Feature feature, Node selected) { + static Set selectElementsOf(FeatureWithSource feature, Node selected) { if (selected instanceof Node.Container) { Node.Container container = (Node.Container) selected; return container.elements().stream() @@ -186,7 +187,7 @@ static Set selectElementsOf(Feature feature, Node select return Collections.emptySet(); } - Feature getFeature() { + FeatureWithSource getFeature() { return feature; } diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberTestDescriptor.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberTestDescriptor.java index 4adecda831..5523a80379 100644 --- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberTestDescriptor.java +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberTestDescriptor.java @@ -2,7 +2,11 @@ import io.cucumber.core.gherkin.Feature; import io.cucumber.core.gherkin.Pickle; +import io.cucumber.junit.platform.engine.CucumberTestDescriptor.FeatureElementDescriptor.ExamplesDescriptor; +import io.cucumber.junit.platform.engine.CucumberTestDescriptor.FeatureElementDescriptor.RuleDescriptor; +import io.cucumber.junit.platform.engine.CucumberTestDescriptor.FeatureElementDescriptor.ScenarioOutlineDescriptor; import io.cucumber.plugin.event.Location; +import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; @@ -17,16 +21,113 @@ import java.util.Set; import java.util.stream.Stream; +import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toSet; abstract class CucumberTestDescriptor extends AbstractTestDescriptor { - protected CucumberTestDescriptor(UniqueId uniqueId, String displayName, TestSource source) { + private static final String RULE_SEGMENT_TYPE = "rule"; + private static final String FEATURE_SEGMENT_TYPE = "feature"; + private static final String SCENARIO_SEGMENT_TYPE = "scenario"; + private static final String EXAMPLES_SEGMENT_TYPE = "examples"; + private static final String EXAMPLE_SEGMENT_TYPE = "example"; + + private CucumberTestDescriptor(UniqueId uniqueId, String displayName, TestSource source) { super(uniqueId, displayName, source); } + static Builder builder(CucumberConfiguration configuration) { + return new Builder(configuration, configuration.namingStrategy()); + } + + static class Builder { + private final CucumberConfiguration configuration; + private final NamingStrategy namingStrategy; + + Builder(CucumberConfiguration configuration, NamingStrategy namingStrategy) { + this.configuration = requireNonNull(configuration); + this.namingStrategy = requireNonNull(namingStrategy); + } + + Optional build( + TestDescriptor parent, FeatureWithSource feature, io.cucumber.plugin.event.Node node + ) { + requireNonNull(parent); + requireNonNull(feature); + requireNonNull(node); + + FeatureSource source = feature.getSource(); + if (node instanceof io.cucumber.plugin.event.Node.Feature) { + return Optional.of(new FeatureDescriptor( + createUniqueId(parent, FEATURE_SEGMENT_TYPE, feature.getUri()), + namingStrategy.name(node), + source.nodeSource(node), + feature.getFeature())); + } + + if (node instanceof io.cucumber.plugin.event.Node.Rule) { + return Optional.of(new RuleDescriptor( + configuration, + createUniqueId(parent, RULE_SEGMENT_TYPE, node.getLocation()), + namingStrategy.name(node), + source.nodeSource(node), + node)); + } + + if (node instanceof io.cucumber.plugin.event.Node.Scenario) { + return Optional.of(new PickleDescriptor( + configuration, + createUniqueId(parent, SCENARIO_SEGMENT_TYPE, node.getLocation()), + namingStrategy.name(node), + source.nodeSource(node), + feature.getFeature().getPickleAt(node))); + } + + if (node instanceof io.cucumber.plugin.event.Node.ScenarioOutline) { + return Optional.of(new ScenarioOutlineDescriptor( + configuration, + createUniqueId(parent, SCENARIO_SEGMENT_TYPE, node.getLocation()), + namingStrategy.name(node), + source.nodeSource(node), + node)); + } + + if (node instanceof io.cucumber.plugin.event.Node.Examples) { + return Optional.of(new ExamplesDescriptor( + configuration, + createUniqueId(parent, EXAMPLES_SEGMENT_TYPE, node.getLocation()), + namingStrategy.name(node), + source.nodeSource(node), + node)); + } + + if (node instanceof io.cucumber.plugin.event.Node.Example) { + Pickle pickle = feature.getFeature().getPickleAt(node); + return Optional.of(new PickleDescriptor( + configuration, + createUniqueId(parent, EXAMPLE_SEGMENT_TYPE, node.getLocation()), + namingStrategy.nameExample(node, pickle), + source.nodeSource(node), + pickle)); + } + throw new IllegalStateException("Got a " + node.getClass() + " but didn't have a case to handle it"); + } + + private static UniqueId createUniqueId(TestDescriptor parent, String segmentType, Location line) { + return createUniqueId(parent, segmentType, String.valueOf(line.getLine())); + } + + private static UniqueId createUniqueId(TestDescriptor parent, String segmentType, String line) { + return parent.getUniqueId().append(segmentType, line); + } + } + + static boolean isFeatureSegment(UniqueId.Segment segment) { + return FEATURE_SEGMENT_TYPE.equals(segment.getType()); + } + protected abstract URI getUri(); protected abstract Location getLocation(); diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureFileResolver.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureFileResolver.java index 0233c0b219..573b2e5bea 100644 --- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureFileResolver.java +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureFileResolver.java @@ -3,24 +3,16 @@ import io.cucumber.core.eventbus.UuidGenerator; import io.cucumber.core.feature.FeatureIdentifier; import io.cucumber.core.feature.FeatureParser; -import io.cucumber.core.gherkin.Feature; -import io.cucumber.core.gherkin.Pickle; import io.cucumber.core.resource.ClassLoaders; import io.cucumber.core.resource.ResourceScanner; import io.cucumber.core.runtime.UuidGeneratorServiceLoader; import io.cucumber.junit.platform.engine.CucumberDiscoverySelectors.FeatureElementSelector; import io.cucumber.junit.platform.engine.CucumberDiscoverySelectors.FeatureWithLinesSelector; -import io.cucumber.junit.platform.engine.CucumberTestDescriptor.FeatureDescriptor; -import io.cucumber.junit.platform.engine.CucumberTestDescriptor.FeatureElementDescriptor.ExamplesDescriptor; -import io.cucumber.junit.platform.engine.CucumberTestDescriptor.FeatureElementDescriptor.RuleDescriptor; -import io.cucumber.junit.platform.engine.CucumberTestDescriptor.FeatureElementDescriptor.ScenarioOutlineDescriptor; -import io.cucumber.junit.platform.engine.CucumberTestDescriptor.PickleDescriptor; import io.cucumber.plugin.event.Node; import org.junit.platform.commons.support.Resource; import org.junit.platform.engine.DiscoveryIssue; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.TestDescriptor; -import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathResourceSelector; @@ -45,11 +37,6 @@ import static io.cucumber.junit.platform.engine.CucumberDiscoverySelectors.FeatureElementSelector.selectElementAt; import static io.cucumber.junit.platform.engine.CucumberDiscoverySelectors.FeatureElementSelector.selectElementsAt; import static io.cucumber.junit.platform.engine.CucumberDiscoverySelectors.FeatureElementSelector.selectElementsOf; -import static io.cucumber.junit.platform.engine.FeatureOrigin.EXAMPLES_SEGMENT_TYPE; -import static io.cucumber.junit.platform.engine.FeatureOrigin.EXAMPLE_SEGMENT_TYPE; -import static io.cucumber.junit.platform.engine.FeatureOrigin.FEATURE_SEGMENT_TYPE; -import static io.cucumber.junit.platform.engine.FeatureOrigin.RULE_SEGMENT_TYPE; -import static io.cucumber.junit.platform.engine.FeatureOrigin.SCENARIO_SEGMENT_TYPE; import static java.util.Collections.singleton; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toSet; @@ -57,17 +44,16 @@ import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; final class FeatureFileResolver implements SelectorResolver { - private final ResourceScanner featureScanner; + private final ResourceScanner featureScanner; - private final CucumberConfiguration configuration; private final FeatureParserWithCaching featureParser; private final Predicate packageFilter; private final DiscoveryIssueReporter issueReporter; + private final CucumberTestDescriptor.Builder testDescriptorBuilder; FeatureFileResolver( CucumberConfiguration configuration, Predicate packageFilter, DiscoveryIssueReporter issueReporter ) { - this.configuration = configuration; this.packageFilter = packageFilter; this.issueReporter = issueReporter; this.featureParser = createFeatureParser(configuration, issueReporter); @@ -75,6 +61,7 @@ final class FeatureFileResolver implements SelectorResolver { ClassLoaders::getDefaultClassLoader, FeatureIdentifier::isFeature, featureParser::parseResource); + this.testDescriptorBuilder = CucumberTestDescriptor.builder(configuration); } private static FeatureParserWithCaching createFeatureParser( @@ -84,8 +71,9 @@ private static FeatureParserWithCaching createFeatureParser( UuidGeneratorServiceLoader uuidGeneratorServiceLoader = new UuidGeneratorServiceLoader(classLoader, options); UuidGenerator uuidGenerator = uuidGeneratorServiceLoader.loadUuidGenerator(); FeatureParser featureParser = new FeatureParser(uuidGenerator::generateId); + FeatureParserWithSource featureParserWithSource = new FeatureParserWithSource(featureParser); FeatureParserWithIssueReporting featureParserWithIssueReporting = new FeatureParserWithIssueReporting( - featureParser, issueReporter); + featureParserWithSource, issueReporter); return new FeatureParserWithCaching(featureParserWithIssueReporting); } @@ -101,7 +89,7 @@ public Resolution resolve(DiscoverySelector selector, Context context) { } public Resolution resolve(FeatureElementSelector selector, Context context) { - Feature feature = selector.getFeature(); + FeatureWithSource feature = selector.getFeature(); Node selected = selector.getElement(); return selected.getParent() .map(parent -> context.addToParent(() -> selectElement(feature, parent), @@ -112,6 +100,12 @@ public Resolution resolve(FeatureElementSelector selector, Context context) { .orElseGet(Resolution::unresolved); } + private Function> createTestDescriptor( + FeatureWithSource feature, Node selected + ) { + return parent -> testDescriptorBuilder.build(parent, feature, selected); + } + public Resolution resolve(FeatureWithLinesSelector selector) { URI uri = selector.getUri(); Set selectors = featureScanner @@ -220,76 +214,6 @@ public Resolution resolve(UniqueIdSelector selector, Context context) { return toResolution(selectors); } - private Function> createTestDescriptor(Feature feature, Node node) { - return parent -> { - NamingStrategy namingStrategy = configuration.namingStrategy(); - FeatureOrigin source = FeatureOrigin.fromUri(feature.getUri()); - String name = namingStrategy.name(node); - TestSource testSource = source.nodeSource(node); - if (node instanceof Node.Feature) { - return Optional.of(new FeatureDescriptor( - parent.getUniqueId().append(FEATURE_SEGMENT_TYPE, feature.getUri().toString()), - name, - testSource, - feature)); - } - - int line = node.getLocation().getLine(); - - if (node instanceof Node.Rule) { - return Optional.of(new RuleDescriptor( - configuration, - parent.getUniqueId().append(RULE_SEGMENT_TYPE, - String.valueOf(line)), - name, - testSource, - node)); - } - - if (node instanceof Node.Scenario) { - return Optional.of(new PickleDescriptor( - configuration, - parent.getUniqueId().append(SCENARIO_SEGMENT_TYPE, - String.valueOf(line)), - name, - testSource, - feature.getPickleAt(node))); - } - - if (node instanceof Node.ScenarioOutline) { - return Optional.of(new ScenarioOutlineDescriptor( - configuration, - parent.getUniqueId().append(SCENARIO_SEGMENT_TYPE, - String.valueOf(line)), - name, - testSource, - node)); - } - - if (node instanceof Node.Examples) { - return Optional.of(new ExamplesDescriptor( - configuration, - parent.getUniqueId().append(EXAMPLES_SEGMENT_TYPE, - String.valueOf(line)), - name, - testSource, - node)); - } - - if (node instanceof Node.Example) { - Pickle pickle = feature.getPickleAt(node); - return Optional.of(new PickleDescriptor( - configuration, - parent.getUniqueId().append(EXAMPLE_SEGMENT_TYPE, - String.valueOf(line)), - namingStrategy.nameExample(node, pickle), - testSource, - pickle)); - } - throw new IllegalStateException("Got a " + node.getClass() + " but didn't have a case to handle it"); - }; - } - private static Resolution toResolution(Set selectors) { if (selectors.isEmpty()) { return Resolution.unresolved(); diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureParserWithCaching.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureParserWithCaching.java index 65616e1480..989530662d 100644 --- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureParserWithCaching.java +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureParserWithCaching.java @@ -1,7 +1,6 @@ package io.cucumber.junit.platform.engine; import io.cucumber.core.exception.CucumberException; -import io.cucumber.core.gherkin.Feature; import io.cucumber.core.resource.Resource; import java.io.IOException; @@ -16,22 +15,22 @@ class FeatureParserWithCaching { - private final Map> cache = new HashMap<>(); + private final Map> cache = new HashMap<>(); private final FeatureParserWithIssueReporting delegate; FeatureParserWithCaching(FeatureParserWithIssueReporting delegate) { this.delegate = delegate; } - Optional parseResource(Resource resource) { + Optional parseResource(Resource resource) { return cache.computeIfAbsent(resource.getUri(), uri -> delegate.parseResource(resource)); } - Optional parseResource(Path resource) { + Optional parseResource(Path resource) { return parseResource(new PathAdapter(resource)); } - Optional parseResource(org.junit.platform.commons.support.Resource resource) { + Optional parseResource(org.junit.platform.commons.support.Resource resource) { return parseResource(new ResourceAdapter(resource)); } diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureParserWithIssueReporting.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureParserWithIssueReporting.java index fd056910b6..ac7d502d6d 100644 --- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureParserWithIssueReporting.java +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureParserWithIssueReporting.java @@ -1,7 +1,5 @@ package io.cucumber.junit.platform.engine; -import io.cucumber.core.feature.FeatureParser; -import io.cucumber.core.gherkin.Feature; import io.cucumber.core.gherkin.FeatureParserException; import io.cucumber.core.resource.Resource; import org.junit.platform.engine.DiscoveryIssue; @@ -13,25 +11,25 @@ class FeatureParserWithIssueReporting { - private final FeatureParser delegate; + private final FeatureParserWithSource delegate; private final DiscoveryIssueReporter issueReporter; - FeatureParserWithIssueReporting(FeatureParser delegate, DiscoveryIssueReporter issueReporter) { + FeatureParserWithIssueReporting(FeatureParserWithSource delegate, DiscoveryIssueReporter issueReporter) { this.delegate = delegate; this.issueReporter = issueReporter; } - Optional parseResource(Resource resource) { + Optional parseResource(Resource resource) { try { return delegate.parseResource(resource); } catch (FeatureParserException e) { - FeatureOrigin featureOrigin = FeatureOrigin.fromUri(resource.getUri()); + FeatureSource featureSource = FeatureSource.of(resource.getUri()); issueReporter.reportIssue(DiscoveryIssue // TODO: Improve parse exception to separate out source uri // and individual errors. .builder(ERROR, e.getMessage()) .cause(e.getCause()) - .source(featureOrigin.source())); + .source(featureSource.source())); return Optional.empty(); } } diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureParserWithSource.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureParserWithSource.java new file mode 100644 index 0000000000..ddc7dbc34a --- /dev/null +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureParserWithSource.java @@ -0,0 +1,22 @@ +package io.cucumber.junit.platform.engine; + +import io.cucumber.core.feature.FeatureParser; +import io.cucumber.core.resource.Resource; + +import java.util.Optional; + +class FeatureParserWithSource { + + private final FeatureParser delegate; + + FeatureParserWithSource(FeatureParser delegate) { + this.delegate = delegate; + } + + Optional parseResource(Resource resource) { + return delegate.parseResource(resource).map(feature -> { + FeatureSource featureSource = FeatureSource.of(resource.getUri()); + return new FeatureWithSource(feature, featureSource); + }); + } +} diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureOrigin.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureSource.java similarity index 64% rename from cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureOrigin.java rename to cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureSource.java index 9d6b648a38..c262a7fc8e 100644 --- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureOrigin.java +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureSource.java @@ -3,7 +3,6 @@ import io.cucumber.plugin.event.Location; import io.cucumber.plugin.event.Node; import org.junit.platform.engine.TestSource; -import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.ClasspathResourceSource; import org.junit.platform.engine.support.descriptor.FilePosition; import org.junit.platform.engine.support.descriptor.FileSource; @@ -12,58 +11,46 @@ import java.net.URI; import static io.cucumber.core.resource.ClasspathSupport.CLASSPATH_SCHEME_PREFIX; +import static org.junit.platform.engine.support.descriptor.ClasspathResourceSource.CLASSPATH_SCHEME; -abstract class FeatureOrigin { - - static final String RULE_SEGMENT_TYPE = "rule"; - static final String FEATURE_SEGMENT_TYPE = "feature"; - static final String SCENARIO_SEGMENT_TYPE = "scenario"; - static final String EXAMPLES_SEGMENT_TYPE = "examples"; - static final String EXAMPLE_SEGMENT_TYPE = "example"; +abstract class FeatureSource { private static FilePosition createFilePosition(Location location) { return FilePosition.from(location.getLine(), location.getColumn()); } - static FeatureOrigin fromUri(URI uri) { - if (ClasspathResourceSource.CLASSPATH_SCHEME.equals(uri.getScheme())) { + static FeatureSource of(URI uri) { + if (CLASSPATH_SCHEME.equals(uri.getScheme())) { if (!uri.getSchemeSpecificPart().startsWith("/")) { // ClasspathResourceSource.from expects all resources to start // with a forward slash uri = URI.create(CLASSPATH_SCHEME_PREFIX + "/" + uri.getRawSchemeSpecificPart()); } ClasspathResourceSource source = ClasspathResourceSource.from(uri); - return new ClasspathFeatureOrigin(source); + return new FeatureClasspathSource(source); } - UriSource source = UriSource.from(uri); if (source instanceof FileSource) { - return new FileFeatureOrigin((FileSource) source); + return new FeatureFileSource((FileSource) source); } - - return new UriFeatureOrigin(source); - - } - - static boolean isFeatureSegment(UniqueId.Segment segment) { - return FEATURE_SEGMENT_TYPE.equals(segment.getType()); + return new FeatureUriSource(source); } abstract TestSource nodeSource(Node node); abstract TestSource source(); - private static class FileFeatureOrigin extends FeatureOrigin { + private static class FeatureFileSource extends FeatureSource { private final FileSource source; - FileFeatureOrigin(FileSource source) { + FeatureFileSource(FileSource source) { this.source = source; } @Override TestSource nodeSource(Node node) { - return FileSource.from(source.getFile(), createFilePosition(node.getLocation())); + return source.withPosition(createFilePosition(node.getLocation())); } @Override @@ -73,11 +60,11 @@ TestSource source() { } - private static class UriFeatureOrigin extends FeatureOrigin { + private static class FeatureUriSource extends FeatureSource { private final UriSource source; - UriFeatureOrigin(UriSource source) { + FeatureUriSource(UriSource source) { this.source = source; } @@ -92,11 +79,11 @@ TestSource source() { } } - private static class ClasspathFeatureOrigin extends FeatureOrigin { + private static class FeatureClasspathSource extends FeatureSource { private final ClasspathResourceSource source; - ClasspathFeatureOrigin(ClasspathResourceSource source) { + FeatureClasspathSource(ClasspathResourceSource source) { this.source = source; } diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureWithSource.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureWithSource.java new file mode 100644 index 0000000000..eca73d7f74 --- /dev/null +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeatureWithSource.java @@ -0,0 +1,28 @@ +package io.cucumber.junit.platform.engine; + +import io.cucumber.core.gherkin.Feature; + +import static java.util.Objects.requireNonNull; + +final class FeatureWithSource { + + private final Feature feature; + private final FeatureSource source; + + FeatureWithSource(Feature feature, FeatureSource source) { + this.feature = requireNonNull(feature); + this.source = requireNonNull(source); + } + + Feature getFeature() { + return feature; + } + + FeatureSource getSource() { + return source; + } + + String getUri() { + return feature.getUri().toString(); + } +}