diff --git a/java.json b/java.json
index f8a13fad..951a0b8c 100644
--- a/java.json
+++ b/java.json
@@ -1,6 +1,6 @@
{
"id": "java",
- "version": "0.11.4",
+ "version": "0.12.0",
"description": "Java support for gauge",
"install": {
"windows": [],
diff --git a/pom.xml b/pom.xml
index 71357668..57e8ff3a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
gauge-java
com.thoughtworks.gauge
gauge-java
- 0.11.4
+ 0.12.0
Java plugin for Gauge
https://github.com/getgauge/gauge-java
diff --git a/src/main/java/com/thoughtworks/gauge/SkipScenarioException.java b/src/main/java/com/thoughtworks/gauge/SkipScenarioException.java
new file mode 100644
index 00000000..c64960ee
--- /dev/null
+++ b/src/main/java/com/thoughtworks/gauge/SkipScenarioException.java
@@ -0,0 +1,12 @@
+package com.thoughtworks.gauge;
+
+public class SkipScenarioException extends RuntimeException {
+ public SkipScenarioException(String message) {
+ super(message);
+ }
+
+ @SuppressWarnings("unused")
+ public SkipScenarioException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/com/thoughtworks/gauge/execution/AbstractExecutionStage.java b/src/main/java/com/thoughtworks/gauge/execution/AbstractExecutionStage.java
index ac8bacfa..8537ac3e 100644
--- a/src/main/java/com/thoughtworks/gauge/execution/AbstractExecutionStage.java
+++ b/src/main/java/com/thoughtworks/gauge/execution/AbstractExecutionStage.java
@@ -20,10 +20,12 @@ public Spec.ProtoExecutionResult executeNext(Spec.ProtoExecutionResult previousS
protected Spec.ProtoExecutionResult mergeExecResults(Spec.ProtoExecutionResult previousStageResult, Spec.ProtoExecutionResult execResult) {
long execTime = execResult.getExecutionTime() + previousStageResult.getExecutionTime();
boolean failed = execResult.getFailed() | previousStageResult.getFailed();
+ boolean skipped = execResult.getSkipScenario() | previousStageResult.getSkipScenario();
Spec.ProtoExecutionResult.Builder builder = Spec.ProtoExecutionResult.newBuilder();
builder.setExecutionTime(execTime);
builder.setFailed(failed);
+ builder.setSkipScenario(skipped);
if (previousStageResult.getFailed()) {
builder.setErrorMessage(previousStageResult.getErrorMessage());
builder.setErrorType(previousStageResult.getErrorType());
diff --git a/src/main/java/com/thoughtworks/gauge/execution/MethodExecutor.java b/src/main/java/com/thoughtworks/gauge/execution/MethodExecutor.java
index 4304ef13..5d18d691 100644
--- a/src/main/java/com/thoughtworks/gauge/execution/MethodExecutor.java
+++ b/src/main/java/com/thoughtworks/gauge/execution/MethodExecutor.java
@@ -7,6 +7,7 @@
import com.thoughtworks.gauge.ClassInstanceManager;
import com.thoughtworks.gauge.ContinueOnFailure;
+import com.thoughtworks.gauge.SkipScenarioException;
import com.thoughtworks.gauge.Util;
import com.thoughtworks.gauge.screenshot.ScreenshotFactory;
import gauge.messages.Spec;
@@ -14,7 +15,7 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
-import java.util.Set;
+import java.util.Optional;
public class MethodExecutor {
private final ClassInstanceManager instanceManager;
@@ -31,17 +32,29 @@ public Spec.ProtoExecutionResult execute(Method method, Object... args) {
long endTime = System.currentTimeMillis();
return Spec.ProtoExecutionResult.newBuilder().setFailed(false).setExecutionTime(endTime - startTime).build();
} catch (Throwable e) {
- boolean recoverable = method.isAnnotationPresent(ContinueOnFailure.class);
- Class[] continuableExceptions = new Class[]{};
- if (recoverable) {
- continuableExceptions = method.getAnnotation(ContinueOnFailure.class).value();
+ long execTime = System.currentTimeMillis() - startTime;
+
+ if (e.getCause() instanceof SkipScenarioException) {
+ return createSkippedExecResult(execTime, (SkipScenarioException) e.getCause());
}
- long endTime = System.currentTimeMillis();
- return createFailureExecResult(endTime - startTime, e, recoverable, continuableExceptions);
+
+ Class>[] continuableExceptions = Optional.ofNullable(method.getAnnotation(ContinueOnFailure.class))
+ .map(ContinueOnFailure::value).
+ orElseGet(() -> new Class>[]{});
+
+ return createFailureExecResult(execTime, e, method.isAnnotationPresent(ContinueOnFailure.class), continuableExceptions);
}
}
- private Spec.ProtoExecutionResult createFailureExecResult(long execTime, Throwable e, boolean recoverable, Class[] continuableExceptions) {
+ private Spec.ProtoExecutionResult createSkippedExecResult(long execTime, SkipScenarioException cause) {
+ return Spec.ProtoExecutionResult.newBuilder()
+ .setSkipScenario(true)
+ .addMessage(Optional.ofNullable(cause.getMessage()).orElse("SKIPPED"))
+ .setExecutionTime(execTime)
+ .build();
+ }
+
+ private Spec.ProtoExecutionResult createFailureExecResult(long execTime, Throwable e, boolean recoverable, Class>[] continuableExceptions) {
Spec.ProtoExecutionResult.Builder builder = Spec.ProtoExecutionResult.newBuilder().setFailed(true);
if (Util.shouldTakeFailureScreenshot()) {
String screenshotFileName = new ScreenshotFactory(instanceManager).getScreenshotBytes();
@@ -49,7 +62,7 @@ private Spec.ProtoExecutionResult createFailureExecResult(long execTime, Throwab
}
if (e.getCause() != null) {
builder.setRecoverableError(false);
- for (Class c : continuableExceptions) {
+ for (Class> c : continuableExceptions) {
if (c.isAssignableFrom(e.getCause().getClass()) && recoverable) {
builder.setRecoverableError(true);
break;
@@ -74,16 +87,4 @@ private String formatStackTrace(Throwable t) {
t.printStackTrace(new PrintWriter(out));
return out.toString();
}
-
- public Spec.ProtoExecutionResult executeMethods(Set methods, Object... args) {
- long totalExecutionTime = 0;
- for (Method method : methods) {
- Spec.ProtoExecutionResult result = execute(method, args);
- totalExecutionTime += result.getExecutionTime();
- if (result.getFailed()) {
- return result;
- }
- }
- return Spec.ProtoExecutionResult.newBuilder().setFailed(false).setExecutionTime(totalExecutionTime).build();
- }
}
diff --git a/src/test/java/com/thoughtworks/gauge/execution/AbstractExecutionStageTest.java b/src/test/java/com/thoughtworks/gauge/execution/AbstractExecutionStageTest.java
index f2029cad..0eae7281 100644
--- a/src/test/java/com/thoughtworks/gauge/execution/AbstractExecutionStageTest.java
+++ b/src/test/java/com/thoughtworks/gauge/execution/AbstractExecutionStageTest.java
@@ -6,6 +6,7 @@
package com.thoughtworks.gauge.execution;
import gauge.messages.Spec;
+import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
@@ -21,94 +22,141 @@ public void testMergingSimpleResultsBothPassing() throws Exception {
assertEquals(2100, result.getExecutionTime());
}
- @Test
- public void testMergingResultsPreviousFailing() throws Exception {
- String screenShot = "1";
-
- Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(true).
- setExecutionTime(100).
- setRecoverableError(false).
- setErrorMessage("Previous failed").
- setStackTrace("Previous stacktrace").
- setFailureScreenshotFile(screenShot).build();
- Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(false).setExecutionTime(1100).build();
- Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);
+ @Nested
+ public class Failing {
+
+ @Test
+ public void testMergingResultsPreviousFailing() throws Exception {
+ String screenShot = "1";
+
+ Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(true)
+ .setExecutionTime(100)
+ .setRecoverableError(false)
+ .setErrorMessage("Previous failed")
+ .setStackTrace("Previous stacktrace")
+ .setFailureScreenshotFile(screenShot).build();
+ Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(false).setExecutionTime(1100).build();
+ Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);
+
+ assertTrue(result.getFailed());
+ assertEquals(1200, result.getExecutionTime());
+ assertEquals("Previous failed", result.getErrorMessage());
+ assertEquals("Previous stacktrace", result.getStackTrace());
+ assertFalse(result.getRecoverableError());
+ assertEquals(screenShot, result.getFailureScreenshotFile());
+ }
- assertTrue(result.getFailed());
- assertEquals(1200, result.getExecutionTime());
- assertEquals("Previous failed", result.getErrorMessage());
- assertEquals("Previous stacktrace", result.getStackTrace());
- assertFalse(result.getRecoverableError());
- assertEquals(screenShot, result.getFailureScreenshotFile());
- }
+ @Test
+ public void testMergingResultsCurrentFailing() throws Exception {
+ String screenShot = "2";
+
+ Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(false).setExecutionTime(100).build();
+ Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(true)
+ .setExecutionTime(100)
+ .setRecoverableError(false)
+ .setErrorMessage("current failed")
+ .setStackTrace("current stacktrace")
+ .setFailureScreenshotFile(screenShot).build();
+ Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);
+
+ assertTrue(result.getFailed());
+ assertEquals(200, result.getExecutionTime());
+ assertEquals("current failed", result.getErrorMessage());
+ assertEquals("current stacktrace", result.getStackTrace());
+ assertFalse(result.getRecoverableError());
+ assertEquals(screenShot, result.getFailureScreenshotFile());
+ }
- @Test
- public void testMergingResultsCurrentFailing() throws Exception {
- String screenShot = "2";
-
- Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(false).setExecutionTime(100).build();
- Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(true).
- setExecutionTime(100).
- setRecoverableError(false).
- setErrorMessage("current failed").
- setStackTrace("current stacktrace").
- setFailureScreenshotFile(screenShot).build();
- Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);
+ @Test
+ public void testMergingResultsBothFailing() throws Exception {
+ String screenShotPrevious = "2";
+ String screenShotCurrent = "hello";
+
+ Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(true)
+ .setExecutionTime(1001)
+ .setRecoverableError(true)
+ .setErrorMessage("previous failed")
+ .setStackTrace("previous stacktrace")
+ .setFailureScreenshotFile(screenShotPrevious).build();
+ Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(true)
+ .setExecutionTime(1002)
+ .setRecoverableError(false)
+ .setErrorMessage("current failed")
+ .setStackTrace("current stacktrace")
+ .setFailureScreenshotFile(screenShotCurrent).build();
+ Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);
+
+ assertTrue(result.getFailed());
+ assertEquals(2003, result.getExecutionTime());
+ assertEquals("previous failed", result.getErrorMessage());
+ assertEquals("previous stacktrace", result.getStackTrace());
+ assertFalse(result.getRecoverableError());
+ assertEquals(screenShotPrevious, result.getFailureScreenshotFile());
+ }
- assertTrue(result.getFailed());
- assertEquals(200, result.getExecutionTime());
- assertEquals("current failed", result.getErrorMessage());
- assertEquals("current stacktrace", result.getStackTrace());
- assertFalse(result.getRecoverableError());
- assertEquals(screenShot, result.getFailureScreenshotFile());
+ @Test
+ public void testMergingResultsCurrentFailingAndIsRecoverable() throws Exception {
+ String screenShotCurrent = "screenShotCurrent.png";
+
+ Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(false).setExecutionTime(1001).build();
+ Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(true)
+ .setExecutionTime(1002)
+ .setRecoverableError(true)
+ .setErrorMessage("current failed")
+ .setStackTrace("current stacktrace")
+ .setFailureScreenshotFile(screenShotCurrent).build();
+ Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);
+
+ assertTrue(result.getFailed());
+ assertEquals(2003, result.getExecutionTime());
+ assertEquals("current failed", result.getErrorMessage());
+ assertEquals("current stacktrace", result.getStackTrace());
+ assertTrue(result.getRecoverableError());
+ assertEquals(screenShotCurrent, result.getFailureScreenshotFile());
+ }
}
- @Test
- public void testMergingResultsBothFailing() throws Exception {
- String screenShotPrevious = "2";
- String screenShotCurrent = "hello";
-
- Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(true).
- setExecutionTime(1001).
- setRecoverableError(true).
- setErrorMessage("previous failed").
- setStackTrace("previous stacktrace").
- setFailureScreenshotFile(screenShotPrevious).build();
- Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(true).
- setExecutionTime(1002).
- setRecoverableError(false).
- setErrorMessage("current failed").
- setStackTrace("current stacktrace").
- setFailureScreenshotFile(screenShotCurrent).build();
- Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);
+ @Nested
+ public class Skipped {
- assertTrue(result.getFailed());
- assertEquals(2003, result.getExecutionTime());
- assertEquals("previous failed", result.getErrorMessage());
- assertEquals("previous stacktrace", result.getStackTrace());
- assertFalse(result.getRecoverableError());
- assertEquals(screenShotPrevious, result.getFailureScreenshotFile());
- }
+ @Test
+ public void testMergingResultsPreviousSkipped() throws Exception {
+ Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setSkipScenario(true)
+ .setExecutionTime(100)
+ .build();
+ Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setSkipScenario(false).setExecutionTime(1100).build();
+ Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);
- @Test
- public void testMergingResultsCurrentFailingAndIsRecoverable() throws Exception {
- String screenShotCurrent = "screenShotCurrent.png";
-
- Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setFailed(false).setExecutionTime(1001).build();
- Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setFailed(true).
- setExecutionTime(1002).
- setRecoverableError(true).
- setErrorMessage("current failed").
- setStackTrace("current stacktrace").
- setFailureScreenshotFile(screenShotCurrent).build();
- Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);
+ assertTrue(result.getSkipScenario());
+ assertEquals(1200, result.getExecutionTime());
+ }
+
+ @Test
+ public void testMergingResultsCurrentSkipped() throws Exception {
+ Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setSkipScenario(false).setExecutionTime(100).build();
+ Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setSkipScenario(true)
+ .setExecutionTime(100)
+ .build();
+ Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);
+
+ assertTrue(result.getSkipScenario());
+ assertEquals(200, result.getExecutionTime());
+ }
+
+ @Test
+ public void testMergingResultsBothSkipped() throws Exception {
+ Spec.ProtoExecutionResult previous = Spec.ProtoExecutionResult.newBuilder().setSkipScenario(true)
+ .setExecutionTime(1001)
+ .build();
+ Spec.ProtoExecutionResult current = Spec.ProtoExecutionResult.newBuilder().setSkipScenario(true)
+ .setExecutionTime(1002)
+ .build();
+ Spec.ProtoExecutionResult result = new TestExecutionStage().mergeExecResults(previous, current);
+
+ assertTrue(result.getSkipScenario());
+ assertEquals(2003, result.getExecutionTime());
+ }
- assertTrue(result.getFailed());
- assertEquals(2003, result.getExecutionTime());
- assertEquals("current failed", result.getErrorMessage());
- assertEquals("current stacktrace", result.getStackTrace());
- assertTrue(result.getRecoverableError());
- assertEquals(screenShotCurrent, result.getFailureScreenshotFile());
}
private static class TestExecutionStage extends AbstractExecutionStage {
diff --git a/src/test/java/com/thoughtworks/gauge/execution/StepExecutionStageTest.java b/src/test/java/com/thoughtworks/gauge/execution/StepExecutionStageTest.java
index f9083ac3..67199c6c 100644
--- a/src/test/java/com/thoughtworks/gauge/execution/StepExecutionStageTest.java
+++ b/src/test/java/com/thoughtworks/gauge/execution/StepExecutionStageTest.java
@@ -19,6 +19,7 @@
import java.lang.reflect.Method;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
@@ -181,6 +182,30 @@ public void testFailingStepMethodExecutionWithNoCOF() throws Exception {
assertEquals("java.lang.RuntimeException: my exception", result.getErrorMessage());
}
+ @Test
+ public void testStepMethodExecutionWithSkipScenarioException() throws Exception {
+ Messages.ExecuteStepRequest executeStepRequest = Messages.ExecuteStepRequest.newBuilder()
+ .setParsedStepText("skip me")
+ .setActualStepText("skip me")
+ .build();
+
+ StepExecutionStage executionStage = new StepExecutionStage(
+ executeStepRequest,
+ new ClassInstanceManager(),
+ new ParameterParsingChain(),
+ mock(StepRegistry.class)
+ );
+
+ MethodExecutor methodExecutor = new MethodExecutor(new ClassInstanceManager());
+ Method skipMethod = this.getClass().getMethod("skipScenarioStep");
+
+ Spec.ProtoExecutionResult result = executionStage.executeStepMethod(methodExecutor, skipMethod);
+
+ assertFalse(result.getFailed());
+ assertTrue(result.getSkipScenario());
+ assertThat(result.getMessageList()).containsExactly("skipping this scenario due to unmet condition");
+ }
+
@ContinueOnFailure
public void foo() {
throw new RuntimeException("my exception");
@@ -222,4 +247,8 @@ public Object table(Object table) {
// Test methods checking methodExecutor with params
return null;
}
+
+ public void skipScenarioStep() {
+ throw new com.thoughtworks.gauge.SkipScenarioException("skipping this scenario due to unmet condition");
+ }
}