diff --git a/README.md b/README.md
index eaa31f98..41a05534 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,9 @@ Requirements
* Redacted some of the output of the config
* Passed the name of the running feature and scenario into the context.
* RemoteWebDriverFactory sets up additional information to pass though via capabilities (current git branch, version)
+* Made the report builder more robust when there are no tests run
+* Modified the Substeps exceptions to limit the stack trace
+* Improved error message when no tests are run
1.0.5
-----
diff --git a/api/src/main/java/com/technophobia/substeps/model/exception/NoTestsRunException.java b/api/src/main/java/com/technophobia/substeps/model/exception/NoTestsRunException.java
new file mode 100644
index 00000000..12032f0e
--- /dev/null
+++ b/api/src/main/java/com/technophobia/substeps/model/exception/NoTestsRunException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright Technophobia Ltd 2012
+ *
+ * This file is part of Substeps.
+ *
+ * Substeps is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Substeps is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Substeps. If not, see .
+ */
+package com.technophobia.substeps.model.exception;
+
+public class NoTestsRunException extends SubstepsException {
+
+ private static final long serialVersionUID = 4050361783327727693L;
+
+ public NoTestsRunException() {
+ super("No tests executed");
+ }
+
+
+}
diff --git a/api/src/main/java/com/technophobia/substeps/model/exception/SubstepsException.java b/api/src/main/java/com/technophobia/substeps/model/exception/SubstepsException.java
index c25fe342..104cf1e6 100644
--- a/api/src/main/java/com/technophobia/substeps/model/exception/SubstepsException.java
+++ b/api/src/main/java/com/technophobia/substeps/model/exception/SubstepsException.java
@@ -18,6 +18,10 @@
*/
package com.technophobia.substeps.model.exception;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Arrays;
+
public class SubstepsException extends RuntimeException {
private static final long serialVersionUID = 4647698987295633906L;
@@ -38,4 +42,35 @@ public SubstepsException(final Throwable cause) {
super(cause);
}
+ @Override
+ public StackTraceElement[] getStackTrace() {
+
+ StackTraceElement[] original = super.getStackTrace();
+ int i = 0;
+ for (; i < original.length; i++){
+ if (original[i].getClassName().contains("substeps")){
+ //
+ }
+ else {
+ break;
+ }
+ }
+
+ return Arrays.copyOf(original, i + 1);
+ }
+
+ @Override
+ public void printStackTrace(PrintStream s) {
+ StackTraceElement[] elems = getStackTrace();
+ setStackTrace(elems);
+ super.printStackTrace(s);
+ }
+
+ @Override
+ public void printStackTrace(PrintWriter s) {
+ StackTraceElement[] elems = getStackTrace();
+ setStackTrace(elems);
+
+ super.printStackTrace(s);
+ }
}
diff --git a/core/src/main/java/com/technophobia/substeps/runner/ExecutionNodeRunner.java b/core/src/main/java/com/technophobia/substeps/runner/ExecutionNodeRunner.java
index b2727890..eba2c430 100644
--- a/core/src/main/java/com/technophobia/substeps/runner/ExecutionNodeRunner.java
+++ b/core/src/main/java/com/technophobia/substeps/runner/ExecutionNodeRunner.java
@@ -25,6 +25,7 @@
import com.technophobia.substeps.execution.MethodExecutor;
import com.technophobia.substeps.execution.node.*;
import com.technophobia.substeps.model.*;
+import com.technophobia.substeps.model.exception.NoTestsRunException;
import com.technophobia.substeps.runner.builder.ExecutionNodeTreeBuilder;
import com.technophobia.substeps.runner.node.RootNodeRunner;
import com.technophobia.substeps.runner.setupteardown.SetupAndTearDown;
@@ -331,7 +332,7 @@ public RootNode run() {
if (!this.nodeExecutionContext.haveTestsBeenRun()) {
- final Throwable t = new IllegalStateException("No tests executed");
+ final Throwable t = new NoTestsRunException();//IllegalStateException("No tests executed");
SubstepExecutionFailure sef = new SubstepExecutionFailure(t, this.rootNode, ExecutionResult.FAILED);
diff --git a/core/src/main/java/com/technophobia/substeps/runner/node/AbstractNodeRunner.java b/core/src/main/java/com/technophobia/substeps/runner/node/AbstractNodeRunner.java
index ba64cd92..e6f03e26 100644
--- a/core/src/main/java/com/technophobia/substeps/runner/node/AbstractNodeRunner.java
+++ b/core/src/main/java/com/technophobia/substeps/runner/node/AbstractNodeRunner.java
@@ -21,6 +21,7 @@
import com.technophobia.substeps.execution.AbstractExecutionNodeVisitor;
import com.technophobia.substeps.execution.ExecutionResult;
import com.technophobia.substeps.execution.node.IExecutionNode;
+import com.technophobia.substeps.execution.node.RootNode;
import com.technophobia.substeps.execution.node.RootNodeExecutionContext;
import com.technophobia.substeps.model.Scope;
import com.technophobia.substeps.model.exception.SubstepsException;
@@ -175,8 +176,15 @@ protected boolean addExpectedChildrenFailureIfNoChildren(final NODE_TYPE node,
final boolean hasChildren = children != null && !children.isEmpty();
if (!hasChildren) {
- context.addFailure(new SubstepExecutionFailure(new IllegalStateException(
- "node should have children but doesn't"), node));
+
+ String msg;
+ if (node instanceof RootNode){
+ msg = "\n\n ** No tests were executed, check Tag configuration in your pom.xml and the tags in the included features **\n\n";
+ }else {
+ msg = "node should have children but doesn't";
+ }
+
+ context.addFailure(new SubstepExecutionFailure(new SubstepsRuntimeException(msg), node));
}
return hasChildren;
diff --git a/core/src/main/scala/org/substeps/report/ReportBuilder.scala b/core/src/main/scala/org/substeps/report/ReportBuilder.scala
index b79dc8cc..fcb7f1de 100644
--- a/core/src/main/scala/org/substeps/report/ReportBuilder.scala
+++ b/core/src/main/scala/org/substeps/report/ReportBuilder.scala
@@ -375,7 +375,11 @@ class ReportBuilder extends IReportBuilder with ReportFrameTemplate with UsageTr
val substepNodeDetails = allNodeDetails.filter(nd => nd.nodeType == "SubstepNode")
val substepDefsByUniqueMethood = substepNodeDetails.groupBy(_.source.get)
- val nextId = allNodeDetails.map(n => n.id).max + 1
+ var nextId = allNodeDetails.map(n => n.id) match {
+ case Nil => 1
+ case ids => ids.max + 1
+ }
+
substepDefsByUniqueMethood.map(e => {
@@ -430,7 +434,10 @@ class ReportBuilder extends IReportBuilder with ReportFrameTemplate with UsageTr
val stepImplsbyUniqueMethood = stepImplNodeDetails.groupBy(_.method.get)
- var nextId = allNodeDetails.map(n => n.id).max + 1
+ var nextId = allNodeDetails.map(n => n.id) match {
+ case Nil => 1
+ case ids => ids.max + 1
+ }
val stepImplNodeDetailsToUsages =
diff --git a/core/src/test/java/com/technophobia/substeps/runner/ExecutionNodeRunnerTest.java b/core/src/test/java/com/technophobia/substeps/runner/ExecutionNodeRunnerTest.java
index 289ab795..0a61e30e 100644
--- a/core/src/test/java/com/technophobia/substeps/runner/ExecutionNodeRunnerTest.java
+++ b/core/src/test/java/com/technophobia/substeps/runner/ExecutionNodeRunnerTest.java
@@ -25,7 +25,9 @@
import com.technophobia.substeps.execution.ImplementationCache;
import com.technophobia.substeps.execution.node.*;
import com.technophobia.substeps.model.Arguments;
+import com.technophobia.substeps.model.exception.NoTestsRunException;
import com.technophobia.substeps.model.exception.SubstepsConfigurationException;
+import com.technophobia.substeps.model.exception.SubstepsRuntimeException;
import com.technophobia.substeps.model.exception.UnimplementedStepException;
import com.technophobia.substeps.runner.setupteardown.Annotations.BeforeAllFeatures;
import com.technophobia.substeps.runner.setupteardown.SetupAndTearDown;
@@ -38,6 +40,8 @@
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.substeps.report.IExecutionResultsCollector;
import java.io.File;
@@ -119,7 +123,7 @@ public void testParseErrorResultsInFailedTest() {
Assert.assertThat(failures.get(0).getThrowableInfo().getMessage(), is(msg));
- Assert.assertThat(failures.get(1).getThrowableInfo().getThrowableClass(), is(IllegalStateException.class.getName()));
+ Assert.assertThat(failures.get(1).getThrowableInfo().getThrowableClass(), is(NoTestsRunException.class.getName()));
Assert.assertThat(failures.get(1).getThrowableInfo().getMessage(), is("No tests executed"));
}
@@ -157,7 +161,7 @@ public void testSubStepDefinitionMatchesStepImplFailure() {
+ TestStepImplementations.class.getName()
+ ".given()] AND matches a sub step definition: [Given something] in [duplicates2.substeps]"));
- Assert.assertThat(failures.get(1).getThrowableInfo().getThrowableClass(), is(IllegalStateException.class.getName()));
+ Assert.assertThat(failures.get(1).getThrowableInfo().getThrowableClass(), is(NoTestsRunException.class.getName()));
Assert.assertThat(failures.get(1).getThrowableInfo().getMessage(), is("No tests executed"));
}
@@ -362,7 +366,7 @@ public void testNoTestsExecutedResultsInTwoFailures() {
runner.run();
final List failures = runner.getFailures();
- verify(mockNotifer, times(1)).onNodeFailed(argThat(is(node)), argThat(any(IllegalStateException.class)));
+ verify(mockNotifer, times(1)).onNodeFailed(argThat(is(node)), argThat(any(NoTestsRunException.class)));
// verify(mockNotifer, times(1)).onNodeFailed(argThat(is(node)), argThat(any(SubstepsRuntimeException.class)));
Assert.assertFalse("expecting some failures", failures.isEmpty());
@@ -417,11 +421,11 @@ public void testScenarioOutlineFailsWithNoExamples() {
Assert.assertThat(failures.size(), is(2));
- Assert.assertThat(failures.get(0).getThrowableInfo().getThrowableClass(), is(IllegalStateException.class.getName()));
+ Assert.assertThat(failures.get(0).getThrowableInfo().getThrowableClass(), is(SubstepsRuntimeException.class.getName()));
Assert.assertThat(failures.get(0).getThrowableInfo().getMessage(), is("node should have children but doesn't"));
- Assert.assertThat(failures.get(1).getThrowableInfo().getThrowableClass(), is(IllegalStateException.class.getName()));
+ Assert.assertThat(failures.get(1).getThrowableInfo().getThrowableClass(), is(NoTestsRunException.class.getName()));
Assert.assertThat(failures.get(1).getThrowableInfo().getMessage(), is("No tests executed"));
}
@@ -574,7 +578,7 @@ public void testBeforeAllFeaturesSetupFailureFailsTheBuild() {
Assert.assertTrue("failure should be marked as setup or tear down", failures.get(0).isSetupOrTearDown());
- Assert.assertThat(failures.get(1).getThrowableInfo().getThrowableClass(), is(IllegalStateException.class.getName()));
+ Assert.assertThat(failures.get(1).getThrowableInfo().getThrowableClass(), is(NoTestsRunException.class.getName()));
Assert.assertThat(failures.get(1).getThrowableInfo().getMessage(), is("No tests executed"));
}
@@ -842,5 +846,17 @@ public void testExecutionNodeTreeBuildingWithScenarioName() {
Assert.assertThat(rootNode.getChildren().get(0).getChildren().size(), is(1));
}
+ private static final Logger log = LoggerFactory.getLogger(ExecutionNodeRunnerTest.class);
+
+
+ @Test
+ public void testNoTestRunException(){
+
+ Throwable e = new NoTestsRunException();
+
+ log.debug("an exception: ", e);
+ }
}
+
+