// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the CPL Common Public License version 1.0.
package fitnesse.responders.run;
import fitnesse.FitNesseContext;
import fitnesse.FitNesseVersion;
import fitnesse.authentication.SecureOperation;
import fitnesse.authentication.SecureResponder;
import fitnesse.authentication.SecureTestOperation;
import fitnesse.http.MockRequest;
import fitnesse.http.MockResponseSender;
import fitnesse.http.Response;
import static fitnesse.responders.run.TestResponderTest.XmlTestUtilities.assertCounts;
import static fitnesse.responders.run.TestResponderTest.XmlTestUtilities.getXmlDocumentFromResults;
import fitnesse.responders.run.formatters.XmlFormatter;
import fitnesse.testutil.FitNesseUtil;
import fitnesse.testutil.FitSocketReceiver;
import fitnesse.wiki.*;
import fitnesse.wikitext.Utils;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import util.Clock;
import util.DateAlteringClock;
import util.DateTimeUtil;
import util.FileUtil;
import static util.RegexTestCase.*;
import util.XmlUtil;
import static util.XmlUtil.getElementByTagName;
import java.io.File;
import java.io.FileInputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestResponderTest {
private static final String TEST_TIME = "12/5/2008 01:19:00";
private WikiPage root;
private MockRequest request;
private TestResponder responder;
private FitNesseContext context;
private Response response;
private MockResponseSender sender;
private WikiPage testPage;
private String results;
private FitSocketReceiver receiver;
private WikiPage errorLogsParentPage;
private PageCrawler crawler;
private File xmlResultsFile;
private XmlChecker xmlChecker = new XmlChecker();
private DateAlteringClock clock;
@Before
public void setUp() throws Exception {
File testDir = new File("TestDir");
testDir.mkdir();
root = InMemoryPage.makeRoot("RooT");
crawler = root.getPageCrawler();
errorLogsParentPage = crawler.addPage(root, PathParser.parse("ErrorLogs"));
request = new MockRequest();
responder = new TestResponder();
responder.setFastTest(true);
context = FitNesseUtil.makeTestContext(root);
receiver = new FitSocketReceiver(0, context.socketDealer);
context.port = receiver.receiveSocket();
clock = new DateAlteringClock(DateTimeUtil.getDateFromString(TEST_TIME)).advanceMillisOnEachQuery();
}
@After
public void tearDown() throws Exception {
receiver.close();
FitNesseUtil.destroyTestContext();
Clock.restoreDefaultClock();
}
@Test
public void testIsValidHtml() throws Exception {
doSimpleRun(passFixtureTable());
assertSubString("<!DOCTYPE html>", results);
assertSubString("</html>", results);
//assertSubString("<base href=\"http://somehost.com:8080/\"", results);
assertSubString("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>", results);
//assertSubString("Command Line Test Results", html);
}
@Test
public void testHead() throws Exception {
doSimpleRun(passFixtureTable());
assertSubString("<div id=\"test-summary\">Running Tests ...</div>", results);
}
@Test
public void testSimpleRun() throws Exception {
doSimpleRun(passFixtureTable());
assertSubString(testPage.getName(), results);
assertSubString("Test Results", results);
assertSubString("class", results);
assertNotSubString("ClassNotFoundException", results);
}
private void doSimpleRun(String fixtureTable) throws Exception {
doSimpleRunWithTags(fixtureTable, null);
}
private void doSimpleRunWithTags(String fixtureTable, String tags) throws Exception {
String simpleRunPageName = "TestPage";
testPage = crawler.addPage(root, PathParser.parse(simpleRunPageName), classpathWidgets() + fixtureTable);
if (tags != null) {
PageData pageData = testPage.getData();
pageData.setAttribute(PageData.PropertySUITES, tags);
testPage.commit(pageData);
}
request.setResource(testPage.getName());
responder.turnOffChunking();
response = responder.makeResponse(context, request);
sender = new MockResponseSender();
sender.doSending(response);
results = sender.sentData();
}
@Test
public void testEmptyTestPage() throws Exception {
PageData data = root.getData();
data.setContent(classpathWidgets());
root.commit(data);
testPage = crawler.addPage(root, PathParser.parse("EmptyTestPage"));
request.setResource(testPage.getName());
response = responder.makeResponse(context, request);
sender = new MockResponseSender();
sender.doSending(response);
sender.sentData();
WikiPagePath errorLogPath = PathParser.parse("ErrorLogs.EmptyTestPage");
WikiPage errorLogPage = crawler.getPage(root, errorLogPath);
String errorLogContent = errorLogPage.getData().getContent();
assertNotSubString("Exception", errorLogContent);
}
@Test
public void testFitSocketGetsClosed() throws Exception {
doSimpleRun(passFixtureTable());
assertTrue(receiver.socket.isClosed());
}
@Test
public void testStandardOutput() throws Exception {
responder.setFastTest(false);
String content = classpathWidgets()
+ outputWritingTable("output1")
+ outputWritingTable("output2")
+ outputWritingTable("output3");
String errorLogContent = doRunAndGetErrorLog(content);
assertHasRegexp("output1", errorLogContent);
assertHasRegexp("output2", errorLogContent);
assertHasRegexp("output3", errorLogContent);
}
@Test
public void testErrorOutput() throws Exception {
responder.setFastTest(false);
String content = classpathWidgets()
+ errorWritingTable("error1")
+ errorWritingTable("error2")
+ errorWritingTable("error3");
String errorLogContent = doRunAndGetErrorLog(content);
assertHasRegexp("error1", errorLogContent);
assertHasRegexp("error2", errorLogContent);
assertHasRegexp("error3", errorLogContent);
}
private String doRunAndGetErrorLog(String content) throws Exception {
WikiPage testPage = crawler.addPage(root, PathParser.parse("TestPage"), content);
request.setResource(testPage.getName());
Response response = responder.makeResponse(context, request);
MockResponseSender sender = new MockResponseSender();
sender.doSending(response);
String results = sender.sentData();
assertHasRegexp("ErrorLog", results);
WikiPage errorLog = errorLogsParentPage.getChildPage(testPage.getName());
return errorLog.getData().getContent();
}
@Test
public void testHasExitValueHeader() throws Exception {
WikiPage testPage = crawler.addPage(root, PathParser.parse("TestPage"), classpathWidgets() + passFixtureTable());
request.setResource(testPage.getName());
Response response = responder.makeResponse(context, request);
MockResponseSender sender = new MockResponseSender();
sender.doSending(response);
String results = sender.sentData();
assertSubString("Exit-Code: 0", results);
}
@Test
public void exitCodeIsCountOfErrors() throws Exception {
doSimpleRun(failFixtureTable());
assertSubString("Exit-Code: 1", results);
}
@Test
public void pageHistoryLinkIsIncluded() throws Exception {
doSimpleRun(passFixtureTable());
assertSubString("href=\"TestPage?pageHistory\">", results);
assertSubString("Page History", results);
}
@Test
public void testFixtureThatCrashes() throws Exception {
responder.setFastTest(false);
WikiPage testPage = crawler.addPage(root, PathParser.parse("TestPage"), classpathWidgets() + crashFixtureTable());
request.setResource(testPage.getName());
Response response = responder.makeResponse(context, request);
MockResponseSender sender = new MockResponseSender();
sender.doSending(response);
String results = sender.sentData();
assertSubString("ErrorLog", results);
}
@Test
public void testResultsIncludeActions() throws Exception {
doSimpleRun(passFixtureTable());
assertSubString("<nav>", results);
}
@Test
public void testResultsHaveHeaderAndFooter() throws Exception {
crawler.addPage(root, PathParser.parse("PageHeader"), "HEADER");
crawler.addPage(root, PathParser.parse("PageFooter"), "FOOTER");
doSimpleRun(passFixtureTable());
assertSubString("HEADER", results);
assertSubString("FOOTER", results);
}
@Test
public void testExecutionStatusAppears() throws Exception {
doSimpleRun(passFixtureTable());
assertHasRegexp("Tests Executed OK", results);
}
@Test
public void simpleXmlFormat() throws Exception {
request.addInput("format", "xml");
doSimpleRun(passFixtureTable());
xmlChecker.assertFitPassFixtureXmlReportIsCorrect();
}
@Test
public void noHistory_skipsHistoryFormatter() throws Exception{
ensureXmlResultFileDoesNotExist(new TestSummary(2, 0, 0, 0));
request.addInput("nohistory", "true");
doSimpleRun(simpleSlimDecisionTable());
assertFalse(xmlResultsFile.exists());
}
private String slimDecisionTable() {
return "!define TEST_SYSTEM {slim}\n" +
"|!-DT:fitnesse.slim.test.TestSlim-!|\n" +
"|string|get string arg?|\n" +
"|right|wrong|\n" +
"|wow|wow|\n";
}
@Test
public void slimXmlFormat() throws Exception {
request.addInput("format", "xml");
ensureXmlResultFileDoesNotExist(new TestSummary(1, 1, 0, 0));
doSimpleRunWithTags(slimDecisionTable(), "zoo");
Document xmlFromFile = getXmlFromFileAndDeleteFile();
xmlChecker.assertXmlReportOfSlimDecisionTableWithZooTagIsCorrect();
xmlChecker.assertXmlHeaderIsCorrect(xmlFromFile);
xmlChecker.assertXmlReportOfSlimDecisionTableWithZooTagIsCorrect();
assertSubString("Exit-Code: 1", results);
}
private void ensureXmlResultFileDoesNotExist(TestSummary counts) {
String resultsFileName = String.format("%s/TestPage/20081205011900_%d_%d_%d_%d.xml",
context.getTestHistoryDirectory(), counts.getRight(), counts.getWrong(), counts.getIgnores(), counts.getExceptions());
xmlResultsFile = new File(resultsFileName);
if (xmlResultsFile.exists())
FileUtil.deleteFile(xmlResultsFile);
}
private Document getXmlFromFileAndDeleteFile() throws Exception {
assertTrue(xmlResultsFile.getAbsolutePath(), xmlResultsFile.exists());
FileInputStream xmlResultsStream = new FileInputStream(xmlResultsFile);
Document xmlDoc = XmlUtil.newDocument(xmlResultsStream);
xmlResultsStream.close();
FileUtil.deleteFile(xmlResultsFile);
return xmlDoc;
}
@Test
public void slimScenarioXmlFormat() throws Exception {
request.addInput("format", "xml");
doSimpleRun(XmlChecker.slimScenarioTable);
xmlChecker.assertXmlReportOfSlimScenarioTableIsCorrect();
}
@Test
public void simpleTextFormatForPassingTest() throws Exception {
request.addInput("format", "text");
doSimpleRun(passFixtureTable());
assertEquals("text/text", response.getContentType());
assertTrue(results.indexOf("\n. ") != -1);
assertTrue(results.indexOf("R:1 W:0 I:0 E:0 TestPage\t(TestPage)") != -1);
assertTrue(results.indexOf("1 Tests,\t0 Failures") != -1);
}
@Test
public void simpleTextFormatForFailingTest() throws Exception {
request.addInput("format", "text");
doSimpleRun(failFixtureTable());
assertEquals("text/text", response.getContentType());
assertTrue(results.indexOf("\nF ") != -1);
assertTrue(results.indexOf("R:0 W:1 I:0 E:0 TestPage\t(TestPage)") != -1);
assertTrue(results.indexOf("1 Tests,\t1 Failures") != -1);
}
@Test
public void simpleTextFormatForErrorTest() throws Exception {
request.addInput("format", "text");
doSimpleRun(errorFixtureTable());
assertEquals("text/text", response.getContentType());
assertTrue(results.indexOf("\nX ") != -1);
assertTrue(results.indexOf("R:0 W:0 I:0 E:1 TestPage\t(TestPage)") != -1);
assertTrue(results.indexOf("1 Tests,\t1 Failures") != -1);
}
@Test
public void testExecutionStatusOk() throws Exception {
doSimpleRun(passFixtureTable());
assertTrue(results.contains(">Tests Executed OK<"));
assertTrue(results.contains("\\\"ok\\\""));
}
@Test
public void debugTest() throws Exception {
responder.setFastTest(false);
request.addInput("debug", "");
doSimpleRun(passFixtureTable());
assertTrue(results.contains(">Tests Executed OK<"));
assertTrue(results.contains("\\\"ok\\\""));
assertTrue("should be fast test", responder.isFastTest());
}
@Test
public void testExecutionStatusOutputCaptured() throws Exception {
responder.setFastTest(false);
doSimpleRun(outputWritingTable("blah"));
assertTrue(results.contains(">Output Captured<"));
assertTrue(results.contains("\\\"output\\\""));
}
@Test
public void testExecutionStatusError() throws Exception {
responder.setFastTest(false);
doSimpleRun(crashFixtureTable());
assertTrue(results.contains(">Errors Occurred<"));
assertTrue(results.contains("\\\"error\\\""));
}
@Test
public void testExecutionStatusErrorHasPriority() throws Exception {
responder.setFastTest(false);
doSimpleRun(errorWritingTable("blah") + crashFixtureTable());
assertTrue(results.contains(">Errors Occurred<"));
}
@Test
public void testTestSummaryAppears() throws Exception {
doSimpleRun(passFixtureTable());
assertHasRegexp(divWithIdAndContent("test-summary", ".*?"), results);
}
@Test
public void testTestSummaryInformationAppears() throws Exception {
doSimpleRun(passFixtureTable());
assertHasRegexp("<script>.*?document\\.getElementById\\(\"test-summary\"\\)\\.innerHTML = \".*?Assertions:.*?\";.*?</script>", results);
assertHasRegexp("<script>.*?document\\.getElementById\\(\"test-summary\"\\)\\.className = \".*?\";.*?</script>", results);
}
@Test
public void testTestSummaryHasRightClass() throws Exception {
doSimpleRun(passFixtureTable());
assertHasRegexp("<script>.*?document\\.getElementById\\(\"test-summary\"\\)\\.className = \"pass\";.*?</script>", results);
}
@Test
public void testTestHasStopped() throws Exception {
String semaphoreName = "testTestHasStopped.semaphore";
File semaphore = new File(semaphoreName);
if (semaphore.exists())
semaphore.delete();
new Thread(makeStopTestsRunnable(semaphore)).start();
doSimpleRun(createAndWaitFixture(semaphoreName));
assertHasRegexp("Testing was interupted", results);
semaphore.delete();
}
private String createAndWaitFixture(String semaphoreName) {
return "!define TEST_SYSTEM {slim}\n" +
"!|fitnesse.testutil.CreateFileAndWaitFixture|" + semaphoreName + "|\n";
}
private Runnable makeStopTestsRunnable(File semaphore) {
return new WaitForSemaphoreThenStopProcesses(semaphore);
}
private class WaitForSemaphoreThenStopProcesses implements Runnable {
private File semaphore;
public WaitForSemaphoreThenStopProcesses(File semaphore) {
this.semaphore = semaphore;
}
public void run() {
waitForSemaphore();
context.runningTestingTracker.stopAllProcesses();
}
private void waitForSemaphore() {
try {
int i = 1000;
while (!semaphore.exists()) {
if (--i <= 0)
break;
Thread.sleep(5);
}
} catch (InterruptedException e) {
}
}
}
@Test
public void testAuthentication_RequiresTestPermission() throws Exception {
assertTrue(responder instanceof SecureResponder);
SecureOperation operation = responder.getSecureOperation();
assertEquals(SecureTestOperation.class, operation.getClass());
}
@Test
public void testNotifyListeners() throws Exception {
MockTestEventListener listener1 = new MockTestEventListener();
MockTestEventListener listener2 = new MockTestEventListener();
TestResponder.registerListener(listener1);
TestResponder.registerListener(listener2);
doSimpleRun(passFixtureTable());
assertEquals(true, listener1.gotPreTestNotification);
assertEquals(true, listener2.gotPreTestNotification);
}
@Test
public void testSuiteSetUpAndTearDownIsCalledIfSingleTestIsRun() throws Exception {
responder.setFastTest(false);
WikiPage suitePage = crawler.addPage(root, PathParser.parse("TestSuite"), classpathWidgets());
WikiPage testPage = crawler.addPage(suitePage, PathParser.parse("TestPage"), outputWritingTable("Output of TestPage"));
crawler.addPage(suitePage, PathParser.parse(PageData.SUITE_SETUP_NAME), outputWritingTable("Output of SuiteSetUp"));
crawler.addPage(suitePage, PathParser.parse(PageData.SUITE_TEARDOWN_NAME), outputWritingTable("Output of SuiteTearDown"));
WikiPagePath testPagePath = crawler.getFullPath(testPage);
String resource = PathParser.render(testPagePath);
request.setResource(resource);
Response response = responder.makeResponse(context, request);
MockResponseSender sender = new MockResponseSender();
sender.doSending(response);
results = sender.sentData();
assertTrue(results.contains(">Output Captured<"));
assertHasRegexp("ErrorLog", results);
WikiPage errorLog = crawler.getPage(errorLogsParentPage, testPagePath);
String errorLogContent = errorLog.getData().getContent();
assertHasRegexp("Output of SuiteSetUp", errorLogContent);
assertHasRegexp("Output of TestPage", errorLogContent);
assertHasRegexp("Output of SuiteTearDown", errorLogContent);
}
@Test
public void testSuiteSetUpDoesNotIncludeSetUp() throws Exception {
responder.setFastTest(false);
WikiPage suitePage = crawler.addPage(root, PathParser.parse("TestSuite"), classpathWidgets());
WikiPage testPage = crawler.addPage(suitePage, PathParser.parse("TestPage"), outputWritingTable("Output of TestPage"));
crawler.addPage(suitePage, PathParser.parse(PageData.SUITE_SETUP_NAME), outputWritingTable("Output of SuiteSetUp"));
crawler.addPage(suitePage, PathParser.parse("SetUp"), outputWritingTable("Output of SetUp"));
WikiPagePath testPagePath = crawler.getFullPath(testPage);
String resource = PathParser.render(testPagePath);
request.setResource(resource);
Response response = responder.makeResponse(context, request);
MockResponseSender sender = new MockResponseSender();
sender.doSending(response);
results = sender.sentData();
WikiPage errorLog = crawler.getPage(errorLogsParentPage, testPagePath);
String errorLogContent = errorLog.getData().getContent();
assertMessagesOccurInOrder(errorLogContent, "Output of SuiteSetUp", "Output of SetUp", "Output of TestPage");
assertMessageHasJustOneOccurrenceOf(errorLogContent, "Output of SetUp");
}
@Test
public void testSuiteTearDownDoesNotIncludeTearDown() throws Exception {
responder.setFastTest(false);
WikiPage suitePage = crawler.addPage(root, PathParser.parse("TestSuite"), classpathWidgets());
WikiPage testPage = crawler.addPage(suitePage, PathParser.parse("TestPage"), outputWritingTable("Output of TestPage"));
crawler.addPage(suitePage, PathParser.parse(PageData.SUITE_TEARDOWN_NAME), outputWritingTable("Output of SuiteTearDown"));
crawler.addPage(suitePage, PathParser.parse("TearDown"), outputWritingTable("Output of TearDown"));
WikiPagePath testPagePath = crawler.getFullPath(testPage);
String resource = PathParser.render(testPagePath);
request.setResource(resource);
Response response = responder.makeResponse(context, request);
MockResponseSender sender = new MockResponseSender();
sender.doSending(response);
results = sender.sentData();
WikiPage errorLog = crawler.getPage(errorLogsParentPage, testPagePath);
String errorLogContent = errorLog.getData().getContent();
assertMessagesOccurInOrder(errorLogContent, "Output of TestPage", "Output of TearDown", "Output of SuiteTearDown");
assertMessageHasJustOneOccurrenceOf(errorLogContent, "Output of TearDown");
}
@Test
public void testSuiteSetUpAndSuiteTearDownWithSetUpAndTearDown() throws Exception {
responder.setFastTest(false);
WikiPage suitePage = crawler.addPage(root, PathParser.parse("TestSuite"), classpathWidgets());
WikiPage testPage = crawler.addPage(suitePage, PathParser.parse("TestPage"), outputWritingTable("Output of TestPage"));
crawler.addPage(suitePage, PathParser.parse(PageData.SUITE_SETUP_NAME), outputWritingTable("Output of SuiteSetUp"));
crawler.addPage(suitePage, PathParser.parse("SetUp"), outputWritingTable("Output of SetUp"));
crawler.addPage(suitePage, PathParser.parse(PageData.SUITE_TEARDOWN_NAME), outputWritingTable("Output of SuiteTearDown"));
crawler.addPage(suitePage, PathParser.parse("TearDown"), outputWritingTable("Output of TearDown"));
WikiPagePath testPagePath = crawler.getFullPath(testPage);
String resource = PathParser.render(testPagePath);
request.setResource(resource);
Response response = responder.makeResponse(context, request);
MockResponseSender sender = new MockResponseSender();
sender.doSending(response);
results = sender.sentData();
WikiPage errorLog = crawler.getPage(errorLogsParentPage, testPagePath);
String errorLogContent = errorLog.getData().getContent();
assertMessagesOccurInOrder(errorLogContent, "Output of SuiteSetUp", "Output of SetUp", "Output of TestPage", "Output of TearDown", "Output of SuiteTearDown");
assertMessageHasJustOneOccurrenceOf(errorLogContent, "Output of SetUp");
}
private void assertMessageHasJustOneOccurrenceOf(String output, String regexp) {
Matcher match = Pattern.compile(regexp, Pattern.MULTILINE | Pattern.DOTALL).matcher(output);
match.find();
boolean found = match.find();
if (found)
fail("The regexp <" + regexp + "> was more than once in: " + output + ".");
}
private void assertMessagesOccurInOrder(String errorLogContent, String... messages) {
int previousIndex = 0, currentIndex = 0;
String previousMsg = "";
for (String msg: messages) {
currentIndex = errorLogContent.indexOf(msg);
assertTrue(String.format("\"%s\" should occur not before \"%s\", but did in \"%s\"", msg, previousMsg, errorLogContent), currentIndex > previousIndex);
previousIndex = currentIndex;
previousMsg = msg;
}
}
private String simpleSlimDecisionTable() {
return "!define TEST_SYSTEM {slim}\n" +
"|!-DT:fitnesse.slim.test.TestSlim-!|\n" +
"|string|get string arg?|\n" +
"|wow|wow|\n";
}
@Test
public void checkHistoryForSimpleSlimTable() throws Exception {
ensureXmlResultFileDoesNotExist(new TestSummary(1, 0, 0, 0));
doSimpleRun(simpleSlimDecisionTable());
Document xmlFromFile = getXmlFromFileAndDeleteFile();
xmlChecker.assertXmlHeaderIsCorrect(xmlFromFile);
assertHasRegexp("<td><span class=\"pass\">wow</span></td>", Utils.unescapeHTML(results));
}
private String errorWritingTable(String message) {
return "\n|!-fitnesse.testutil.ErrorWritingFixture-!|\n" +
"|" + message + "|\n\n";
}
private String outputWritingTable(String message) {
return "\n|!-fitnesse.testutil.OutputWritingFixture-!|\n" +
"|" + message + "|\n\n";
}
private String classpathWidgets() {
return "!path classes\n";
}
private String crashFixtureTable() {
return "|!-fitnesse.testutil.CrashFixture-!|\n";
}
private String passFixtureTable() {
return "|!-fitnesse.testutil.PassFixture-!|\n";
}
private String failFixtureTable() {
return "|!-fitnesse.testutil.FailFixture-!|\n";
}
private String errorFixtureTable() {
return "|!-fitnesse.testutil.ErrorFixture-!|\n";
}
class XmlChecker {
private Element testResultsElement;
public void assertXmlHeaderIsCorrect(Document testResultsDocument) throws Exception {
testResultsElement = testResultsDocument.getDocumentElement();
assertEquals("testResults", testResultsElement.getNodeName());
String version = XmlUtil.getTextValue(testResultsElement, "FitNesseVersion");
assertEquals(new FitNesseVersion().toString(), version);
}
public void assertFitPassFixtureXmlReportIsCorrect() throws Exception {
assertHeaderOfXmlDocumentsInResponseIsCorrect();
Element result = getElementByTagName(testResultsElement, "result");
Element counts = getElementByTagName(result, "counts");
assertCounts(counts, "1", "0", "0", "0");
String runTimeInMillis = XmlUtil.getTextValue(result, "runTimeInMillis");
assertThat(Long.parseLong(runTimeInMillis), is(not(0L)));
Element tags = getElementByTagName(result, "tags");
assertNull(tags);
String content = XmlUtil.getTextValue(result, "content");
assertSubString("PassFixture", content);
String relativePageName = XmlUtil.getTextValue(result, "relativePageName");
assertEquals("TestPage", relativePageName);
}
public void assertXmlReportOfSlimDecisionTableWithZooTagIsCorrect() throws Exception {
String instructionContents[] = {"make", "table", "beginTable", "reset", "setString", "execute", "getStringArg", "reset", "setString", "execute", "getStringArg", "endTable"};
String instructionResults[] = {"OK", "EXCEPTION", "EXCEPTION", "EXCEPTION", "VOID", "VOID", "right", "EXCEPTION", "VOID", "VOID", "wow", "EXCEPTION"};
assertHeaderOfXmlDocumentsInResponseIsCorrect();
Element result = getElementByTagName(testResultsElement, "result");
Element counts = getElementByTagName(result, "counts");
assertCounts(counts, "1", "1", "0", "0");
String tags = XmlUtil.getTextValue(result, "tags");
assertEquals("zoo", tags);
Element tables = getElementByTagName(result, "tables");
assertNotNull(tables);
NodeList tableList = tables.getElementsByTagName("table");
assertNotNull(tableList);
assertEquals(1, tableList.getLength());
Element tableElement = (Element) tableList.item(0);
String tableName = XmlUtil.getTextValue(tableElement, "name");
assertNotNull(tableName);
assertEquals("decisionTable_0", tableName);
assertEquals("[[pass(DT:fitnesse.slim.test.TestSlim)],[string,get string arg?],[right,[right] fail(expected [wrong])],[wow,pass(wow)]]", tableElementToString(tableElement));
Element instructions = getElementByTagName(result, "instructions");
NodeList instructionList = instructions.getElementsByTagName("instructionResult");
assertEquals(instructionContents.length, instructionList.getLength());
for (int i = 0; i < instructionContents.length; i++) {
Element instructionElement = (Element) instructionList.item(i);
assertInstructionHas(instructionElement, instructionContents[i]);
}
for (int i = 0; i < instructionResults.length; i++) {
Element instructionElement = (Element) instructionList.item(i);
assertResultHas(instructionElement, instructionResults[i]);
}
checkExpectation(instructionList, 0, "decisionTable_0_0", "0", "0", "right", "ConstructionExpectation", "OK", "DT:fitnesse.slim.test.TestSlim", "pass(DT:fitnesse.slim.test.TestSlim)");
checkExpectation(instructionList, 4, "decisionTable_0_4", "0", "2", "ignored", "VoidReturnExpectation", "/__VOID__/", "right", "right");
checkExpectation(instructionList, 6, "decisionTable_0_6", "1", "2", "wrong", "ReturnedValueExpectation", "right", "wrong", "[right] fail(expected [wrong])");
checkExpectation(instructionList, 8, "decisionTable_0_8", "0", "3", "ignored", "VoidReturnExpectation", "/__VOID__/", "wow", "wow");
checkExpectation(instructionList, 10, "decisionTable_0_10", "1", "3", "right", "ReturnedValueExpectation", "wow", "wow", "pass(wow)");
}
private String tableElementToString(Element tableElement) {
StringBuilder result = new StringBuilder();
result.append("[");
rowsToString(tableElement, result);
result.append("]");
return result.toString();
}
private void rowsToString(Element tableElement, StringBuilder result) {
NodeList rows = tableElement.getElementsByTagName("row");
for (int row = 0; row < rows.getLength(); row++) {
result.append("[");
Element rowElement = (Element) rows.item(row);
colsToString(result, rowElement);
result.append("],");
}
result.deleteCharAt(result.length() - 1);
}
private void colsToString(StringBuilder result, Element rowElement) {
NodeList cols = rowElement.getElementsByTagName("col");
for (int col = 0; col < cols.getLength(); col++) {
Element colElement = (Element) cols.item(col);
result.append(colElement.getFirstChild().getNodeValue());
result.append(",");
}
result.deleteCharAt(result.length() - 1);
}
public final static String slimScenarioTable =
"!define TEST_SYSTEM {slim}\n" +
"\n" +
"!|scenario|f|a|\n" +
"|check|echo int|@a|@a|\n" +
"\n" +
"!|script|fitnesse.slim.test.TestSlim|\n" +
"\n" +
"!|f|\n" +
"|a|\n" +
"|1|\n" +
"|2|\n";
public void assertXmlReportOfSlimScenarioTableIsCorrect() throws Exception {
assertHeaderOfXmlDocumentsInResponseIsCorrect();
Element result = getElementByTagName(testResultsElement, "result");
Element counts = getElementByTagName(result, "counts");
assertCounts(counts, "2", "0", "0", "0");
String runTimeInMillis = XmlUtil.getTextValue(result, "runTimeInMillis");
assertThat(Long.parseLong(runTimeInMillis), is(not(0L)));
assertTablesInSlimScenarioAreCorrect(result);
assertInstructionsOfSlimScenarioTableAreCorrect(result);
}
private void assertInstructionsOfSlimScenarioTableAreCorrect(Element result) throws Exception {
Element instructions = getElementByTagName(result, "instructions");
NodeList instructionList = instructions.getElementsByTagName("instructionResult");
assertInstructionContentsOfSlimScenarioAreCorrect(instructionList);
assertInstructionResultsOfSlimScenarioAreCorrect(instructionList);
assertExpectationsOfSlimScenarioAreCorrect(instructionList);
}
private void assertExpectationsOfSlimScenarioAreCorrect(NodeList instructionList) throws Exception {
checkExpectation(instructionList, 0, "scriptTable_1_0", "1", "0", "right", "ConstructionExpectation", "OK", "fitnesse.slim.test.TestSlim", "pass(fitnesse.slim.test.TestSlim)");
checkExpectation(instructionList, 1, "decisionTable_2_0/scriptTable_0_0", "3", "1", "right", "ReturnedValueExpectation", "1", "1", "pass(1)");
checkExpectation(instructionList, 2, "decisionTable_2_1/scriptTable_0_0", "3", "1", "right", "ReturnedValueExpectation", "2", "2", "pass(2)");
}
private void assertInstructionResultsOfSlimScenarioAreCorrect(NodeList instructionList) throws Exception {
String instructionResults[] = {"OK", "1", "2"};
for (int i = 0; i < instructionResults.length; i++) {
Element instructionElement = (Element) instructionList.item(i);
assertResultHas(instructionElement, instructionResults[i]);
}
}
private void assertInstructionContentsOfSlimScenarioAreCorrect(NodeList instructionList) throws Exception {
String instructionContents[] = {"make", "call", "call"};
assertEquals(instructionContents.length, instructionList.getLength());
for (int i = 0; i < instructionContents.length; i++) {
Element instructionElement = (Element) instructionList.item(i);
assertInstructionHas(instructionElement, instructionContents[i]);
}
}
private void assertTablesInSlimScenarioAreCorrect(Element result) throws Exception {
Element tables = getElementByTagName(result, "tables");
NodeList tableList = tables.getElementsByTagName("table");
assertEquals(5, tableList.getLength());
String tableNames[] = {"scenarioTable_0", "scriptTable_1", "decisionTable_2", "decisionTable_2_0/scriptTable_0", "decisionTable_2_1/scriptTable_0"};
String tableValues[][][] = {
{
{"scenario", "f", "a"},
{"check", "echo int", "@a", "@a"}
},
{
{"script", "pass(fitnesse.slim.test.TestSlim)"}
},
{
{"f"},
{"a"},
{"1", "pass(scenario:decisionTable_2_0/scriptTable_0)"},
{"2", "pass(scenario:decisionTable_2_1/scriptTable_0)"}
},
{
{"scenario", "f", "a"},
{"check", "echo int", "1", "pass(1)"}
},
{
{"scenario", "f", "a"},
{"check", "echo int", "2", "pass(2)"}
}
};
for (int tableIndex = 0; tableIndex < tableList.getLength(); tableIndex++) {
assertEquals(tableNames[tableIndex], XmlUtil.getTextValue((Element) tableList.item(tableIndex), "name"));
Element tableElement = (Element) tableList.item(tableIndex);
NodeList rowList = tableElement.getElementsByTagName("row");
for (int rowIndex = 0; rowIndex < rowList.getLength(); rowIndex++) {
NodeList colList = ((Element) rowList.item(rowIndex)).getElementsByTagName("col");
for (int colIndex = 0; colIndex < colList.getLength(); colIndex++)
assertEquals(tableValues[tableIndex][rowIndex][colIndex], XmlUtil.getElementText((Element) colList.item(colIndex)));
}
}
}
private void checkExpectation(NodeList instructionList, int index, String id, String col, String row, String status, String type, String actual, String expected, String message) throws Exception {
Element instructionElement = (Element) instructionList.item(index);
Element expectation = getElementByTagName(instructionElement, "expectation");
assertEquals(id, XmlUtil.getTextValue(expectation, "instructionId"));
assertEquals(status, XmlUtil.getTextValue(expectation, "status"));
assertEquals(type, XmlUtil.getTextValue(expectation, "type"));
assertEquals(col, XmlUtil.getTextValue(expectation, "col"));
assertEquals(row, XmlUtil.getTextValue(expectation, "row"));
assertEquals(actual, XmlUtil.getTextValue(expectation, "actual"));
assertEquals(expected, XmlUtil.getTextValue(expectation, "expected"));
assertEquals(message, XmlUtil.getTextValue(expectation, "evaluationMessage"));
}
private void assertInstructionHas(Element instructionElement, String content) throws Exception {
String instruction = XmlUtil.getTextValue(instructionElement, "instruction");
assertTrue(String.format("instruction %s should contain: %s", instruction, content), instruction.indexOf(content) != -1);
}
private void assertResultHas(Element instructionElement, String content) throws Exception {
String result = XmlUtil.getTextValue(instructionElement, "slimResult");
assertTrue(String.format("result %s should contain: %s", result, content), result.indexOf(content) != -1);
}
private void assertHeaderOfXmlDocumentsInResponseIsCorrect() throws Exception {
assertEquals("text/xml", response.getContentType());
Document testResultsDocument = getXmlDocumentFromResults(results);
xmlChecker.assertXmlHeaderIsCorrect(testResultsDocument);
}
}
public static class XmlTestUtilities {
public static Document getXmlDocumentFromResults(String results) throws Exception {
String endOfXml = "</testResults>";
String startOfXml = "<?xml";
int xmlStartIndex = results.indexOf(startOfXml);
int xmlEndIndex = results.indexOf(endOfXml) + endOfXml.length();
String xmlString = results.substring(xmlStartIndex, xmlEndIndex);
return XmlUtil.newDocument(xmlString);
}
public static void assertCounts(Element counts, String right, String wrong, String ignores, String exceptions)
throws Exception {
assertEquals(right, XmlUtil.getTextValue(counts, "right"));
assertEquals(wrong, XmlUtil.getTextValue(counts, "wrong"));
assertEquals(ignores, XmlUtil.getTextValue(counts, "ignores"));
assertEquals(exceptions, XmlUtil.getTextValue(counts, "exceptions"));
}
}
}