(Collections.nCopies(testSystemListenerShowInstructions,""));
}
@Override
@@ -90,7 +129,6 @@ public void testStarted(TestPage testPage) {
super.testStarted(testPage);
String fullPathName = testPage.getFullPath();
-
announceStartNewTest(getRelativeName(), fullPathName);
}
@@ -177,6 +215,79 @@ public void testSystemStarted(TestSystem testSystem) {
writeData(insertScript.html());
}
}
+
+
+
+ protected void showAssertionResult(Assertion assertion, String testResult, boolean overwriteLastMessage) {
+ if(testSystemListenerShowInstructions >0){
+ try {
+ String instructionText;
+ String position;
+ Expectation expectation = assertion.getExpectation();
+ if (expectation instanceof TableCell) {
+ TableCell cell = (TableCell) expectation;
+ position = String.format("% 3d,% 3d", cell.getRow(), cell.getCol());
+ } else {
+ position = " ";
+ }
+ assertion.getInstruction();
+ instructionText = assertion.getInstruction().toString();
+ instructionText = position + ": " + instructionText + "-->" + testResult;
+ instructionText = HtmlUtil.escapeHTML(instructionText);
+ if (overwriteLastMessage){
+ this.instructionsHtmlText.removeLast();
+ } else {
+ this.instructionsHtmlText.removeFirst();
+ }
+ this.instructionsHtmlText.addLast(instructionText);
+ String allInstructionsText = this.instructionsHtmlText.stream().collect(Collectors.joining("
"));
+ String html = ""+allInstructionsText+"
";
+ String insertScript = JavascriptUtil.makeReplaceElementScript("step-by-step-Id2", html).html();
+ writeData(insertScript);
+ } catch (Exception e){
+ String html = e.getMessage();
+ }
+ }
+ if(testSystemListenerShowHtmlTable){
+ try{
+ Expectation expectation = assertion.getExpectation();
+ if (expectation instanceof TableCell) {
+ TableCell cell = (TableCell) expectation;
+ Table t = cell.getTable();
+ if (t instanceof HtmlTable) {
+ HtmlTable ht = (HtmlTable) t;
+ String html = ht.getTableNode().toHtml().toString();
+ String insertScript = JavascriptUtil.makeReplaceElementScript("step-by-step-Id", html).html();
+ testOutputChunk(null, insertScript);
+ String expandScript = JavascriptUtil.expandCurrentRow("step-by-step-Id").html();
+ testOutputChunk(null, expandScript);
+ }
+ }
+ if (testSystemListenerSleep > 0)
+ Thread.sleep(testSystemListenerSleep);
+ } catch (Exception e){
+ String em = e.getMessage();
+ }
+ }
+ }
+
+ @Override
+ public void testAssertionVerified(Assertion assertion, TestResult testResult) {
+ String resultString = testResult != null ? testResult.toString() : "VOID";
+ showAssertionResult(assertion,resultString, true);
+ }
+
+ @Override
+ public void testExceptionOccurred(Assertion assertion, ExceptionResult exceptionResult) {
+ String resultString = exceptionResult!= null ? exceptionResult.toString() : "EXCEPTION";
+ showAssertionResult(assertion,resultString, true);
+ }
+
+ @Override
+ public void testAssertionWillBeExecuted(Assertion assertion) {
+ String resultString = "in progress";
+ showAssertionResult(assertion,resultString, false);
+ }
@Override
protected String makeSummaryContent() {
@@ -189,9 +300,11 @@ protected String makeSummaryContent() {
return summaryContent;
}
+
protected boolean hasTestSummaries() {
return testSummariesPresent;
}
+
}
diff --git a/src/fitnesse/resources/templates/testPage.vm b/src/fitnesse/resources/templates/testPage.vm
index 838a9fd92..f2e8d44cb 100644
--- a/src/fitnesse/resources/templates/testPage.vm
+++ b/src/fitnesse/resources/templates/testPage.vm
@@ -16,6 +16,13 @@ $!headerContent.render()
## Filled with stop/output buttons
+
+## Current Instruction updates here
+
+
+## Current Table updates here
+
+
#if ($multipleTestsRun)
Test Summaries
diff --git a/src/fitnesse/testrunner/MultipleTestsRunner.java b/src/fitnesse/testrunner/MultipleTestsRunner.java
index 54f28ef70..a4446fa99 100755
--- a/src/fitnesse/testrunner/MultipleTestsRunner.java
+++ b/src/fitnesse/testrunner/MultipleTestsRunner.java
@@ -224,6 +224,12 @@ public void testAssertionVerified(Assertion assertion, TestResult testResult) {
public void testExceptionOccurred(Assertion assertion, ExceptionResult exceptionResult) {
formatters.testExceptionOccurred(assertion, exceptionResult);
}
+
+ @Override
+ public void testAssertionWillBeExecuted(Assertion assertion) {
+ formatters.testAssertionWillBeExecuted(assertion);
+ }
+
}
private boolean isNotStopped() {
diff --git a/src/fitnesse/testsystems/CompositeTestSystemListener.java b/src/fitnesse/testsystems/CompositeTestSystemListener.java
index 58b3883c0..4a7fe05b8 100644
--- a/src/fitnesse/testsystems/CompositeTestSystemListener.java
+++ b/src/fitnesse/testsystems/CompositeTestSystemListener.java
@@ -60,4 +60,10 @@ public void testExceptionOccurred(Assertion assertion, ExceptionResult exception
for (TestSystemListener listener : listeners)
listener.testExceptionOccurred(assertion, exceptionResult);
}
+
+ @Override
+ public void testAssertionWillBeExecuted(Assertion assertion) {
+ for (TestSystemListener listener : listeners)
+ listener.testAssertionWillBeExecuted(assertion);
+ }
}
diff --git a/src/fitnesse/testsystems/TableCell.java b/src/fitnesse/testsystems/TableCell.java
index a5f9e528d..94bddf629 100644
--- a/src/fitnesse/testsystems/TableCell.java
+++ b/src/fitnesse/testsystems/TableCell.java
@@ -1,5 +1,7 @@
package fitnesse.testsystems;
+import fitnesse.testsystems.slim.Table;
+
/**
* This interface can be implemented by Expectation's to provide extra information for reporting.
*/
@@ -8,4 +10,6 @@ public interface TableCell {
int getCol();
int getRow();
+
+ Table getTable();
}
diff --git a/src/fitnesse/testsystems/TestSystemListener.java b/src/fitnesse/testsystems/TestSystemListener.java
index 3dbab98e2..a7ab0535b 100644
--- a/src/fitnesse/testsystems/TestSystemListener.java
+++ b/src/fitnesse/testsystems/TestSystemListener.java
@@ -43,4 +43,8 @@ default void testAssertionVerified(Assertion assertion, TestResult testResult) {
default void testExceptionOccurred(Assertion assertion, ExceptionResult exceptionResult) {
}
+
+ /* This is only useful for interactive Listeners, it is called before the assertion is passed to the SUT */
+ default void testAssertionWillBeExecuted(Assertion assertion) {
+ }
}
diff --git a/src/fitnesse/testsystems/slim/SlimTestSystem.java b/src/fitnesse/testsystems/slim/SlimTestSystem.java
index 90a4389ae..13da49784 100755
--- a/src/fitnesse/testsystems/slim/SlimTestSystem.java
+++ b/src/fitnesse/testsystems/slim/SlimTestSystem.java
@@ -20,6 +20,12 @@
import static fitnesse.slim.SlimServer.*;
public abstract class SlimTestSystem implements TestSystem {
+ // BULK - Process a full table by the Slim Client in one go
+ // SINGLE - Process a single instruction and give control back to the test system
+ // Default Mode is BULK
+ public static final String SLIM_MODE = "slim.mode";
+ // This will force the mode SINGLE to allow a more interactive user experience
+ public static final String SLIM_SHOW = "slim.show";
private final SlimClient slimClient;
private final CompositeTestSystemListener testSystemListener;
private final String testSystemName;
@@ -41,6 +47,19 @@ public SlimTestContext getTestContext() {
return testContext;
}
+ private boolean isModeSingle(){
+ String sbys = getTestContext().getPageToTest().getVariable(SLIM_MODE);
+ if (sbys != null){
+ if ("SINGLE".equals(sbys)) return true;
+ }
+ sbys = getTestContext().getPageToTest().getVariable(SLIM_SHOW);
+ if (sbys != null){
+ return true;
+ }
+ return false;
+ }
+
+
@Override
public String getName() {
return testSystemName;
@@ -118,11 +137,13 @@ protected SlimTestContextImpl createTestContext(TestPage testPage) {
protected void processTable(SlimTable table, boolean isSuiteTearDownPage) throws TestExecutionException {
List assertions = table.getAssertions();
- final Map instructionResults;
+ Map instructionResults;
if (stopTestCalled && !table.isTearDown()) {
instructionResults = Collections.emptyMap();
+ evaluateTables(assertions, instructionResults);
} else if (ignoreAllTestsCalled && !table.isTearDown()){
instructionResults = Collections.emptyMap();
+ evaluateTables(assertions, instructionResults);
} else {
boolean tearDownOfAlreadyStartedTest = stopTestCalled && table.isTearDown();
if(ignoreAllTestsCalled && table.isTearDown()){
@@ -130,71 +151,100 @@ protected void processTable(SlimTable table, boolean isSuiteTearDownPage) throws
}
if (stopSuiteCalled && !isSuiteTearDownPage && !tearDownOfAlreadyStartedTest) {
instructionResults = Collections.emptyMap();
+ evaluateTables(assertions, instructionResults);
} else {
- instructionResults = slimClient.invokeAndGetResponse(SlimAssertion.getInstructions(assertions));
+ if (isModeSingle()){
+ boolean IgnoreTestTable = false;
+ for (SlimAssertion assertion : assertions) {
+ List oneAssertion = new ArrayList<>();
+ oneAssertion.add(assertion);
+ testAssertionWillBeExecuted(assertion);
+ instructionResults = slimClient.invokeAndGetResponse(SlimAssertion.getInstructions(oneAssertion));
+ final String instructionId = assertion.getInstruction().getId();
+ Object instructionResult = instructionResults.get(instructionId);
+ IgnoreTestTable = evaluateAssertion(instructionResult,IgnoreTestTable, assertion, instructionId);
+ }
+ } else {
+ instructionResults = slimClient.invokeAndGetResponse(SlimAssertion.getInstructions(assertions));
+ evaluateTables(assertions, instructionResults);
+ }
}
}
- evaluateTables(assertions, instructionResults);
+
}
protected void evaluateTables(List assertions, Map instructionResults) throws SlimCommunicationException {
boolean IgnoreTestTable = false;
for (SlimAssertion a : assertions) {
final String key = a.getInstruction().getId();
- Object returnValue = instructionResults.get(key);
-
- //Ignore management
- if(!ignoreAllTestsCalled) {
- if (returnValue != null && returnValue.toString().contains(EXCEPTION_IGNORE_ALL_TESTS_TAG)) {
- ignoreAllTestsCalled = IgnoreTestTable = true;
- } else if (returnValue != null && returnValue.toString().contains(EXCEPTION_IGNORE_SCRIPT_TEST_TAG)) {
- IgnoreTestTable = true;
- } else if (IgnoreTestTable) {
- returnValue = "IGNORE_SCRIPT_TEST";
- }
- } else {
- returnValue = "IGNORE_SCRIPT_TEST";
+ Object instructionResult = instructionResults.get(key);
+ IgnoreTestTable = evaluateAssertion(instructionResult, IgnoreTestTable, a, key);
+ }
+ }
+
+ private boolean evaluateAssertion(Object InstructionResult, boolean IgnoreTestTable, SlimAssertion a, String key)
+ throws SlimCommunicationException {
+
+
+ //Ignore management
+ if(!ignoreAllTestsCalled) {
+ if (InstructionResult != null && InstructionResult.toString().contains(EXCEPTION_IGNORE_ALL_TESTS_TAG)) {
+ ignoreAllTestsCalled = IgnoreTestTable = true;
+ } else if (InstructionResult != null && InstructionResult.toString().contains(EXCEPTION_IGNORE_SCRIPT_TEST_TAG)) {
+ IgnoreTestTable = true;
+ } else if (IgnoreTestTable) {
+ InstructionResult = "IGNORE_SCRIPT_TEST";
}
- //Exception management
- if (returnValue != null && returnValue instanceof String && ((String) returnValue).startsWith(EXCEPTION_TAG)) {
- SlimExceptionResult exceptionResult = new SlimExceptionResult(key, (String) returnValue);
- if (exceptionResult.isStopTestException()) {
- stopTestCalled = true;
- stopSuiteCalled = PageData.SUITE_SETUP_NAME.equals(testContext.getPageToTest().getName());
- }
- if (exceptionResult.isStopSuiteException()) {
- stopTestCalled = stopSuiteCalled = true;
- }
- exceptionResult = a.getExpectation().evaluateException(exceptionResult);
- if (exceptionResult != null) {
- if (!exceptionResult.isCatchException())
- testExceptionOccurred(a, exceptionResult);
- else
- testAssertionVerified(a, exceptionResult.catchTestResult());
- }
+ } else {
+ InstructionResult = "IGNORE_SCRIPT_TEST";
+ }
+ //Exception management
+ if (InstructionResult != null && InstructionResult instanceof String && ((String) InstructionResult).startsWith(EXCEPTION_TAG)) {
+ SlimExceptionResult exceptionResult = new SlimExceptionResult(key, (String) InstructionResult);
+ if (exceptionResult.isStopTestException()) {
+ //IgnoreTestTable = stopTestCalled = true;
+ stopTestCalled = true;
+ stopSuiteCalled = PageData.SUITE_SETUP_NAME.equals(testContext.getPageToTest().getName());
+ }
+ if (exceptionResult.isStopSuiteException()) {
+ //IgnoreTestTable = stopTestCalled = stopSuiteCalled = true;
+ stopTestCalled = stopSuiteCalled = true;
+ }
+ exceptionResult = a.getExpectation().evaluateException(exceptionResult);
+ if (exceptionResult != null) {
+ if (!exceptionResult.isCatchException())
+ testExceptionOccurred(a, exceptionResult);
+ else
+ testAssertionVerified(a, exceptionResult.catchTestResult());
} else {
- //Normal results
- TestResult testResult = a.getExpectation().evaluateExpectation(returnValue);
- testAssertionVerified(a, testResult);
-
- //Retrieve variables set during expectation step
- if (testResult != null) {
- Map variables = testResult.getVariablesToStore();
- if (variables != null) {
- List instructions = new ArrayList<>(variables.size());
- int i = 0;
- for (Entry variable : variables.entrySet()) {
- instructions.add(new AssignInstruction("assign_" + i++, variable.getKey(), variable.getValue()));
- }
- //Store variables in context
- if (i > 0) {
- slimClient.invokeAndGetResponse(instructions);
- }
+ // Silently ignored exception for optional decision table functions
+ // see class SilentReturnExpectation
+ testAssertionVerified(a, null);
+ }
+
+ } else {
+ //Normal results
+ TestResult testResult = a.getExpectation().evaluateExpectation(InstructionResult);
+ testAssertionVerified(a, testResult);
+
+ //Retrieve variables set during expectation step
+ if (testResult != null) {
+ Map variables = testResult.getVariablesToStore();
+ if (variables != null) {
+ List instructions = new ArrayList<>(variables.size());
+ int i = 0;
+ for (Entry variable : variables.entrySet()) {
+ instructions.add(new AssignInstruction("assign_" + i++, variable.getKey(), variable.getValue()));
+ }
+ //Store variables in context
+ if (i > 0) {
+ slimClient.invokeAndGetResponse(instructions);
}
}
}
}
+ return IgnoreTestTable;
}
protected void testOutputChunk(TestPage testPage, String output) {
@@ -222,6 +272,9 @@ protected void testExceptionOccurred(Assertion assertion, ExceptionResult except
testSystemListener.testExceptionOccurred(assertion, exceptionResult);
}
+ protected void testAssertionWillBeExecuted(Assertion assertion) {
+ testSystemListener.testAssertionWillBeExecuted(assertion);
+ }
// Ensure testSystemStopped is called only once per test system. First call counts.
protected void testSystemStopped(Throwable e) {
if (testSystemIsStopped) return;
diff --git a/src/fitnesse/testsystems/slim/tables/SlimTable.java b/src/fitnesse/testsystems/slim/tables/SlimTable.java
index 8ddcb67db..746781212 100644
--- a/src/fitnesse/testsystems/slim/tables/SlimTable.java
+++ b/src/fitnesse/testsystems/slim/tables/SlimTable.java
@@ -302,6 +302,10 @@ public int getCol() {
public int getRow() {
return row;
}
+ @Override
+ public Table getTable() {
+ return table;
+ }
// Used only by TestXmlFormatter.SlimTestXmlFormatter
public String getExpected() {