diff --git a/cucumber-core/src/main/java/io/cucumber/core/options/Constants.java b/cucumber-core/src/main/java/io/cucumber/core/options/Constants.java
index 6f314e4eea..d6ada2d7d1 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/options/Constants.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/options/Constants.java
@@ -32,7 +32,7 @@ public final class Constants {
*
* Limits the number of scenarios to be executed to a specific amount.
*
- * By default scenarios are executed.
+ * By default, scenarios are executed.
*/
public static final String EXECUTION_LIMIT_PROPERTY_NAME = "cucumber.execution.limit";
@@ -42,10 +42,12 @@ public final class Constants {
* Valid values are {@code lexical}, {@code reverse}, {@code random} or
* {@code random:[seed]}.
*
- * By default features are executed in lexical file name order
+ * By default, features are executed in lexical file name order
*/
public static final String EXECUTION_ORDER_PROPERTY_NAME = "cucumber.execution.order";
+ public static final String EXECUTION_SKIP_TAGS_PROPERTY_NAME = "cucumber.execution.skip.tags";
+
/**
* Property name used to enable wip execution: {@value}
*
diff --git a/cucumber-core/src/main/java/io/cucumber/core/options/RuntimeOptions.java b/cucumber-core/src/main/java/io/cucumber/core/options/RuntimeOptions.java
index 795d74b946..b3c60b5730 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/options/RuntimeOptions.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/options/RuntimeOptions.java
@@ -62,6 +62,7 @@ public final class RuntimeOptions implements
// For context see: https://mattwynne.net/new-beginning
private boolean publishQuiet = true;
private boolean enablePublishPlugin;
+ private List skipTagExpressions = new ArrayList<>();
private RuntimeOptions() {
@@ -174,6 +175,11 @@ public Class extends UuidGenerator> getUuidGeneratorClass() {
return uuidGeneratorClass;
}
+ @Override
+ public List getSkipTagExpressions() {
+ return skipTagExpressions;
+ }
+
void setUuidGeneratorClass(Class extends UuidGenerator> uuidGeneratorClass) {
this.uuidGeneratorClass = uuidGeneratorClass;
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runner/Options.java b/cucumber-core/src/main/java/io/cucumber/core/runner/Options.java
index 0fe0ffb807..987246c9b7 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runner/Options.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runner/Options.java
@@ -3,6 +3,7 @@
import io.cucumber.core.backend.ObjectFactory;
import io.cucumber.core.eventbus.UuidGenerator;
import io.cucumber.core.snippets.SnippetType;
+import io.cucumber.tagexpressions.Expression;
import java.net.URI;
import java.util.List;
@@ -19,4 +20,6 @@ public interface Options {
Class extends UuidGenerator> getUuidGeneratorClass();
+ List getSkipTagExpressions();
+
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runner/Runner.java b/cucumber-core/src/main/java/io/cucumber/core/runner/Runner.java
index 6e560a05a1..372fcc833f 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runner/Runner.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runner/Runner.java
@@ -17,6 +17,7 @@
import io.cucumber.plugin.event.Location;
import io.cucumber.plugin.event.SnippetsSuggestedEvent;
import io.cucumber.plugin.event.SnippetsSuggestedEvent.Suggestion;
+import io.cucumber.tagexpressions.Expression;
import java.net.URI;
import java.util.ArrayList;
@@ -138,15 +139,28 @@ private void buildBackendWorlds() {
}
private TestCase createTestCaseForPickle(Pickle pickle) {
+ ExecutionMode executionMode = getExecutionMode(pickle);
+
if (pickle.getSteps().isEmpty()) {
- return new TestCase(bus.generateId(), emptyList(), emptyList(), emptyList(), pickle,
- runnerOptions.isDryRun());
+ return new TestCase(bus.generateId(), emptyList(), emptyList(), emptyList(), pickle, executionMode);
}
List testSteps = createTestStepsForPickleSteps(pickle);
List beforeHooks = createTestStepsForBeforeHooks(pickle.getTags());
List afterHooks = createTestStepsForAfterHooks(pickle.getTags());
- return new TestCase(bus.generateId(), testSteps, beforeHooks, afterHooks, pickle, runnerOptions.isDryRun());
+ return new TestCase(bus.generateId(), testSteps, beforeHooks, afterHooks, pickle, executionMode);
+ }
+
+ private ExecutionMode getExecutionMode(Pickle pickle) {
+ List skipTagExpression = runnerOptions.getSkipTagExpressions();
+ if (!skipTagExpression.isEmpty()
+ && skipTagExpression.stream().allMatch(expression -> expression.evaluate(pickle.getTags()))) {
+ return ExecutionMode.SKIP;
+ } else if (runnerOptions.isDryRun()) {
+ return ExecutionMode.DRY_RUN;
+ } else {
+ return ExecutionMode.RUN;
+ }
}
private void disposeBackendWorlds() {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runner/TestCase.java b/cucumber-core/src/main/java/io/cucumber/core/runner/TestCase.java
index 63e2a72fc6..f67b5f2283 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runner/TestCase.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runner/TestCase.java
@@ -22,8 +22,6 @@
import java.util.UUID;
import java.util.stream.Collectors;
-import static io.cucumber.core.runner.ExecutionMode.DRY_RUN;
-import static io.cucumber.core.runner.ExecutionMode.RUN;
import static io.cucumber.messages.Convertor.toMessage;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;
@@ -42,14 +40,14 @@ final class TestCase implements io.cucumber.plugin.event.TestCase {
List beforeHooks,
List afterHooks,
Pickle pickle,
- boolean dryRun
+ ExecutionMode executionMode
) {
this.id = id;
this.testSteps = testSteps;
this.beforeHooks = beforeHooks;
this.afterHooks = afterHooks;
this.pickle = pickle;
- this.executionMode = dryRun ? DRY_RUN : RUN;
+ this.executionMode = executionMode;
}
private static io.cucumber.messages.types.Group makeMessageGroup(
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/HookTestStepTest.java b/cucumber-core/src/test/java/io/cucumber/core/runner/HookTestStepTest.java
index 569cf827e3..8ec6326cee 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/HookTestStepTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/HookTestStepTest.java
@@ -39,7 +39,7 @@ class HookTestStepTest {
Collections.emptyList(),
Collections.emptyList(),
feature.getPickles().get(0),
- false);
+ ExecutionMode.RUN);
private final EventBus bus = mock(EventBus.class);
private final UUID testExecutionId = UUID.randomUUID();
private final TestCaseState state = new TestCaseState(bus, testExecutionId, testCase);
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/PickleStepTestStepTest.java b/cucumber-core/src/test/java/io/cucumber/core/runner/PickleStepTestStepTest.java
index 60e561bde9..4f50916ab1 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/PickleStepTestStepTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/PickleStepTestStepTest.java
@@ -58,7 +58,7 @@ class PickleStepTestStepTest {
" Given I have 4 cukes in my belly\n");
private final Pickle pickle = feature.getPickles().get(0);
private final TestCase testCase = new TestCase(UUID.randomUUID(), Collections.emptyList(), Collections.emptyList(),
- Collections.emptyList(), pickle, false);
+ Collections.emptyList(), pickle, ExecutionMode.RUN);
private final EventBus bus = mock(EventBus.class);
private final UUID testExecutionId = UUID.randomUUID();
private final TestCaseState state = new TestCaseState(bus, testExecutionId, testCase);
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateResultTest.java b/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateResultTest.java
index f1082fe48e..9ed971493d 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateResultTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateResultTest.java
@@ -49,7 +49,7 @@ class TestCaseStateResultTest {
Collections.emptyList(),
Collections.emptyList(),
feature.getPickles().get(0),
- false));
+ ExecutionMode.RUN));
@BeforeEach
void setup() {
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateTest.java b/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateTest.java
index dc13053d72..688ee3ed28 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateTest.java
@@ -45,7 +45,7 @@ private TestCaseState createTestCaseState(Feature feature) {
Collections.emptyList(),
Collections.emptyList(),
feature.getPickles().get(0),
- false));
+ ExecutionMode.RUN));
}
@Test
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseTest.java b/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseTest.java
index 04fd4c5676..463a7c3287 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseTest.java
@@ -88,7 +88,7 @@ void run_wraps_execute_in_test_case_started_and_finished_events() throws Throwab
private TestCase createTestCase(PickleStepTestStep... steps) {
return new TestCase(UUID.randomUUID(), asList(steps), Collections.emptyList(), Collections.emptyList(),
- pickle(), false);
+ pickle(), ExecutionMode.RUN);
}
private Pickle pickle() {
diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/Constants.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/Constants.java
index 06a6573e11..579583179a 100644
--- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/Constants.java
+++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/Constants.java
@@ -35,6 +35,8 @@ public final class Constants {
*/
public static final String EXECUTION_DRY_RUN_PROPERTY_NAME = io.cucumber.core.options.Constants.EXECUTION_DRY_RUN_PROPERTY_NAME;
+ public static final String EXECUTION_SKIP_TAGS_PROPERTY_NAME = io.cucumber.core.options.Constants.EXECUTION_SKIP_TAGS_PROPERTY_NAME;
+
/**
* Tag replacement pattern for the exclusive resource templates: {@value}
*
diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberEngineOptions.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberEngineOptions.java
index f12b963b12..95a842e4d1 100644
--- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberEngineOptions.java
+++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberEngineOptions.java
@@ -28,6 +28,7 @@
import static io.cucumber.core.resource.ClasspathSupport.CLASSPATH_SCHEME_PREFIX;
import static io.cucumber.junit.platform.engine.Constants.ANSI_COLORS_DISABLED_PROPERTY_NAME;
import static io.cucumber.junit.platform.engine.Constants.EXECUTION_DRY_RUN_PROPERTY_NAME;
+import static io.cucumber.junit.platform.engine.Constants.EXECUTION_SKIP_TAGS_PROPERTY_NAME;
import static io.cucumber.junit.platform.engine.Constants.FEATURES_PROPERTY_NAME;
import static io.cucumber.junit.platform.engine.Constants.FILTER_NAME_PROPERTY_NAME;
import static io.cucumber.junit.platform.engine.Constants.FILTER_TAGS_PROPERTY_NAME;
@@ -41,6 +42,7 @@
import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PUBLISH_TOKEN_PROPERTY_NAME;
import static io.cucumber.junit.platform.engine.Constants.SNIPPET_TYPE_PROPERTY_NAME;
import static io.cucumber.junit.platform.engine.Constants.UUID_GENERATOR_PROPERTY_NAME;
+import static java.util.Collections.emptyList;
class CucumberEngineOptions implements
io.cucumber.core.plugin.Options,
@@ -164,6 +166,14 @@ public Class extends UuidGenerator> getUuidGeneratorClass() {
.orElse(null);
}
+ @Override
+ public List getSkipTagExpressions() {
+ return configurationParameters
+ .get(EXECUTION_SKIP_TAGS_PROPERTY_NAME, TagExpressionParser::parse)
+ .map(Collections::singletonList)
+ .orElse(emptyList());
+ }
+
boolean isParallelExecutionEnabled() {
return configurationParameters
.getBoolean(PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME)
@@ -185,6 +195,6 @@ List featuresWithLines() {
.sorted(Comparator.comparing(FeatureWithLines::uri))
.distinct()
.collect(Collectors.toList()))
- .orElse(Collections.emptyList());
+ .orElse(emptyList());
}
}