// 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 java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; 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 fitnesse.FitNesseContext; import fitnesse.FitNesseVersion; import fitnesse.authentication.SecureOperation; import fitnesse.authentication.SecureResponder; import fitnesse.authentication.SecureTestOperation; import fitnesse.html.HtmlUtil; import fitnesse.http.MockRequest; import fitnesse.http.MockResponseSender; import fitnesse.http.Response; import fitnesse.http.SimpleResponse; import fitnesse.responders.testHistory.ExecutionLogResponder; import fitnesse.testsystems.TestSummary; import fitnesse.testutil.FitNesseUtil; import fitnesse.util.Clock; import fitnesse.util.DateAlteringClock; import fitnesse.util.DateTimeUtil; import fitnesse.util.XmlUtil; import fitnesse.wiki.*; import util.FileUtil; import static fitnesse.responders.run.TestResponderTest.XmlTestUtilities.assertCounts; import static fitnesse.responders.run.TestResponderTest.XmlTestUtilities.getXmlDocumentFromResults; import static fitnesse.util.XmlUtil.getElementByTagName; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static util.RegexTestCase.assertHasRegexp; import static util.RegexTestCase.assertNotSubString; import static util.RegexTestCase.assertSubString; import static util.RegexTestCase.divWithIdAndContent; public class TestResponderTest { private static final String TEST_TIME = "12/5/2008 01:19:00"; private WikiPage root; private MockRequest request; private SuiteResponder responder; private FitNesseContext context; private Response response; private MockResponseSender sender; private WikiPage testPage; private String results; private File xmlResultsFile; private XmlChecker xmlChecker = new XmlChecker(); private boolean debug; @Before public void setUp() throws Exception { debug = true; File testDir = new File("TestDir"); testDir.mkdir(); Properties properties = new Properties(); context = FitNesseUtil.makeTestContext(); root = context.getRootPage(); request = new MockRequest(); responder = new TestResponder(); properties.setProperty("FITNESSE_PORT", String.valueOf(context.port)); new DateAlteringClock(DateTimeUtil.getDateFromString(TEST_TIME)).advanceMillisOnEachQuery(); } @After public void tearDown() throws Exception { 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\"><div id=\"progressBar\">Preparing Tests ...</div></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 { if (debug) request.addInput("debug", "true"); String simpleRunPageName = "TestPage"; testPage = WikiPageUtil.addPage(root, PathParser.parse(simpleRunPageName), classpathWidgets() + fixtureTable); if (tags != null) { PageData pageData = testPage.getData(); pageData.setAttribute(PageData.PropertySUITES, tags); testPage.commit(pageData); } request.addInput("requestParam", "2"); request.setResource(testPage.getName()); 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 = WikiPageUtil.addPage(root, PathParser.parse("EmptyTestPage"), ""); request.setResource(testPage.getName()); response = responder.makeResponse(context, request); sender = new MockResponseSender(); sender.doSending(response); sender.sentData(); String errorLogContent = getExecutionLog(); assertNotSubString("Exception", errorLogContent); assertSubString("No execution log available.", errorLogContent); } @Test public void testStandardOutput() throws Exception { 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 { 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 = WikiPageUtil.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("\\?executionLog", results); return getExecutionLog(); } private String getExecutionLog() throws Exception { return ((SimpleResponse) new ExecutionLogResponder().makeResponse(context, request)).getContent(); } @Test public void testHasExitValueHeader() throws Exception { WikiPage testPage = WikiPageUtil.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 { responder.turnOffChunking(); doSimpleRun(passFixtureTable()); assertSubString("<a href=\"TestPage?pageHistory\"", results); assertSubString("Page History", results); } @Test public void testTestIdIsSentAsHeader() throws Exception { WikiPage testPage = WikiPageUtil.addPage(root, PathParser.parse("TestPage"), ""); request.setResource(testPage.getName()); Response response = responder.makeResponse(context, request); MockResponseSender sender = new MockResponseSender(); sender.doSending(response); String results = sender.sentData(); assertSubString("X-FitNesse-Test-Id: ", results); } @Test public void testFixtureThatCrashes() throws Exception { WikiPage testPage = WikiPageUtil.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("?executionLog", results); } @Test public void testResultsIncludeActions() throws Exception { doSimpleRun(passFixtureTable()); assertSubString("<nav", results); } @Test public void testResultsDoHaveHeaderAndFooter() throws Exception { WikiPageUtil.addPage(root, PathParser.parse("PageHeader"), "HEADER"); WikiPageUtil.addPage(root, PathParser.parse("PageFooter"), "FOOTER"); doSimpleRun(passFixtureTable()); assertSubString("HEADER", results); assertSubString("FOOTER", results); } @Test public void testExecutionLogLinkAppears() throws Exception { doSimpleRun(passFixtureTable()); assertHasRegexp("class=\\\\\"ok\\\\\">Execution Log", results); } @Test public void simpleXmlFormat() throws Exception { responder.turnOffChunking(); 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 { responder.turnOffChunking(); request.addInput("format", "xml"); ensureXmlResultFileDoesNotExist(new TestSummary(0, 1, 0, 0)); doSimpleRunWithTags(slimDecisionTable(), "zoo"); Document xmlFromFile = getXmlFromFileAndDeleteFile(); xmlChecker.assertXmlReportOfSlimDecisionTableWithZooTagIsCorrect(); xmlChecker.assertXmlHeaderIsCorrect(xmlFromFile); xmlChecker.assertXmlReportOfSlimDecisionTableWithZooTagIsCorrect(); } @Test public void slimXmlFormatGivesErrorCountAsExitCode() throws Exception { request.addInput("format", "xml"); ensureXmlResultFileDoesNotExist(new TestSummary(0, 1, 0, 0)); doSimpleRunWithTags(slimDecisionTable(), "zoo"); getXmlFromFileAndDeleteFile(); assertSubString("Exit-Code: 1", results); } private void ensureXmlResultFileDoesNotExist(TestSummary counts) throws IOException { 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 { responder.turnOffChunking(); request.addInput("format", "xml"); doSimpleRun(XmlChecker.SLIM_SCENARIO_TABLE); xmlChecker.assertXmlReportOfSlimScenarioTableIsCorrect(); } @Test public void simpleTextFormatForPassingTest() throws Exception { request.addInput("format", "text"); doSimpleRun(passFixtureTable()); assertEquals("text/text", response.getContentType()); assertTrue(results.contains("\n. ")); assertTrue(results.contains("R:1 W:0 I:0 E:0 TestPage\t(TestPage)")); assertTrue(results.contains("1 Tests,\t0 Failures")); } @Test public void simpleTextFormatForFailingTest() throws Exception { request.addInput("format", "text"); doSimpleRun(failFixtureTable()); assertEquals("text/text", response.getContentType()); assertTrue(results.contains("\nF ")); assertTrue(results.contains("R:0 W:1 I:0 E:0 TestPage\t(TestPage)")); assertTrue(results.contains("1 Tests,\t1 Failures")); } @Test public void simpleTextFormatForErrorTest() throws Exception { request.addInput("format", "text"); doSimpleRun(errorFixtureTable()); assertEquals("text/text", response.getContentType()); assertTrue(results.contains("\nX ")); assertTrue(results.contains("R:0 W:0 I:0 E:1 TestPage\t(TestPage)")); assertTrue(results.contains("1 Tests,\t1 Failures")); } @Test public void testExecutionStatusOk() throws Exception { doSimpleRun(passFixtureTable()); assertTrue(results.contains(">Execution Log<")); assertTrue(results.contains("\\\"ok\\\"")); } @Test public void debugTest() throws Exception { request.addInput("debug", ""); doSimpleRun(passFixtureTable()); assertTrue(results.contains(">Execution Log<")); assertTrue(results.contains("\\\"ok\\\"")); assertTrue("should be fast test", responder.isDebug()); } @Test public void testExecutionStatusError() throws Exception { debug = false; doSimpleRun(crashFixtureTable()); assertTrue(results.contains(">Execution Log<")); assertTrue(results.contains("\\\"error\\\"")); } @Test public void testExecutionStatusErrorHasPriority() throws Exception { debug = false; doSimpleRun(errorWritingTable("blah") + crashFixtureTable()); assertTrue(results.contains("class=\\\"error\\\">Execution Log<")); } @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(new WaitForSemaphoreThenStopProcesses(semaphore)).start(); doSimpleRun(createAndWaitFixture(semaphoreName)); assertHasRegexp("Testing was interrupted", results); semaphore.delete(); } private String createAndWaitFixture(String semaphoreName) { return "!define TEST_SYSTEM {slim}\n" + // Set a timeout, so the command can be processed async "!define slim.flags {-s 10 }\n" + "!|fitnesse.testutil.CreateFileAndWaitFixture|" + semaphoreName + "|\n"; } private class WaitForSemaphoreThenStopProcesses implements Runnable { private File semaphore; public WaitForSemaphoreThenStopProcesses(File semaphore) { this.semaphore = semaphore; } @Override public void run() { waitForSemaphore(); SuiteResponder.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 testSuiteSetUpAndTearDownIsCalledIfSingleTestIsRun() throws Exception { WikiPage suitePage = WikiPageUtil.addPage(root, PathParser.parse("TestSuite"), classpathWidgets()); WikiPage testPage = WikiPageUtil.addPage(suitePage, PathParser.parse("TestPage"), outputWritingTable("Output of TestPage")); WikiPageUtil.addPage(suitePage, PathParser.parse(PageData.SUITE_SETUP_NAME), outputWritingTable("Output of SuiteSetUp")); WikiPageUtil.addPage(suitePage, PathParser.parse(PageData.SUITE_TEARDOWN_NAME), outputWritingTable("Output of SuiteTearDown")); PageData data = testPage.getData(); WikiPageProperty properties = data.getProperties(); properties.set(PageData.PropertySUITES, "Test Page tags"); testPage.commit(data); WikiPagePath testPagePath = testPage.getPageCrawler().getFullPath(); 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(">Execution Log<")); assertHasRegexp("\\?executionLog", results); assertSubString("Test Page tags", results); String errorLogContent = getExecutionLog(); assertHasRegexp("Output of SuiteSetUp", errorLogContent); assertHasRegexp("Output of TestPage", errorLogContent); assertHasRegexp("Output of SuiteTearDown", errorLogContent); } @Test public void testSuiteSetUpDoesNotIncludeSetUp() throws Exception { WikiPage suitePage = WikiPageUtil.addPage(root, PathParser.parse("TestSuite"), classpathWidgets()); WikiPage testPage = WikiPageUtil.addPage(suitePage, PathParser.parse("TestPage"), outputWritingTable("Output of TestPage")); WikiPageUtil.addPage(suitePage, PathParser.parse(PageData.SUITE_SETUP_NAME), outputWritingTable("Output of SuiteSetUp")); WikiPageUtil.addPage(suitePage, PathParser.parse("SetUp"), outputWritingTable("Output of SetUp")); WikiPagePath testPagePath = testPage.getPageCrawler().getFullPath(); String resource = PathParser.render(testPagePath); request.setResource(resource); Response response = responder.makeResponse(context, request); MockResponseSender sender = new MockResponseSender(); sender.doSending(response); results = sender.sentData(); String errorLogContent = getExecutionLog(); assertMessagesOccurInOrder(errorLogContent, "Output of SuiteSetUp", "Output of SetUp", "Output of TestPage"); assertMessageHasJustOneOccurrenceOf(errorLogContent, "Output of SetUp"); } @Test public void testSuiteTearDownDoesNotIncludeTearDown() throws Exception { WikiPage suitePage = WikiPageUtil.addPage(root, PathParser.parse("TestSuite"), classpathWidgets()); WikiPage testPage = WikiPageUtil.addPage(suitePage, PathParser.parse("TestPage"), outputWritingTable("Output of TestPage")); WikiPageUtil.addPage(suitePage, PathParser.parse(PageData.SUITE_TEARDOWN_NAME), outputWritingTable("Output of SuiteTearDown")); WikiPageUtil.addPage(suitePage, PathParser.parse("TearDown"), outputWritingTable("Output of TearDown")); WikiPagePath testPagePath = testPage.getPageCrawler().getFullPath(); String resource = PathParser.render(testPagePath); request.setResource(resource); Response response = responder.makeResponse(context, request); MockResponseSender sender = new MockResponseSender(); sender.doSending(response); results = sender.sentData(); String errorLogContent = getExecutionLog(); assertMessagesOccurInOrder(errorLogContent, "Output of TestPage", "Output of TearDown", "Output of SuiteTearDown"); assertMessageHasJustOneOccurrenceOf(errorLogContent, "Output of TearDown"); } @Test public void testSuiteSetUpAndSuiteTearDownWithSetUpAndTearDown() throws Exception { WikiPage suitePage = WikiPageUtil.addPage(root, PathParser.parse("TestSuite"), classpathWidgets()); WikiPage testPage = WikiPageUtil.addPage(suitePage, PathParser.parse("TestPage"), outputWritingTable("Output of TestPage")); WikiPageUtil.addPage(suitePage, PathParser.parse(PageData.SUITE_SETUP_NAME), outputWritingTable("Output of SuiteSetUp")); WikiPageUtil.addPage(suitePage, PathParser.parse("SetUp"), outputWritingTable("Output of SetUp")); WikiPageUtil.addPage(suitePage, PathParser.parse(PageData.SUITE_TEARDOWN_NAME), outputWritingTable("Output of SuiteTearDown")); WikiPageUtil.addPage(suitePage, PathParser.parse("TearDown"), outputWritingTable("Output of TearDown")); WikiPagePath testPagePath = testPage.getPageCrawler().getFullPath(); String resource = PathParser.render(testPagePath); request.setResource(resource); Response response = responder.makeResponse(context, request); MockResponseSender sender = new MockResponseSender(); sender.doSending(response); results = sender.sentData(); String errorLogContent = getExecutionLog(); 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>", HtmlUtil.unescapeHTML(results)); } @Test public void xmlFormatterShouldContainExecutionLog() throws Exception { WikiPage suitePage = WikiPageUtil.addPage(root, PathParser.parse("TestSuite"), classpathWidgets()); WikiPage testPage = WikiPageUtil.addPage(suitePage, PathParser.parse("TestPage"), outputWritingTable("Output of TestPage")); WikiPagePath testPagePath = testPage.getPageCrawler().getFullPath(); String resource = PathParser.render(testPagePath); request.setResource(resource); request.addInput("format", "xml"); request.addInput("nochunk", "nochunk"); Response response = responder.makeResponse(context, request); MockResponseSender sender = new MockResponseSender(); sender.doSending(response); results = sender.sentData(); assertHasRegexp("<executionLog>", results); assertHasRegexp("<testSystem>fit:fit.FitServer</testSystem>", results); assertHasRegexp("<exitCode>0</exitCode>", results); assertHasRegexp("<stdOut>Output of TestPage.*</stdOut>", results); assertHasRegexp("<stdErr></stdErr>", 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"}; String instructionContents[] = {"make", "setString", "getStringArg", "setString", "getStringArg"}; String instructionResults[] = {"pass(DT:fitnesse.slim.test.TestSlim)", null, "fail(a=right;e=wrong)", null, "pass(wow)"}; 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 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", "pass", "ConstructionExpectation", null, null, "DT:fitnesse.slim.test.TestSlim"); checkExpectation(instructionList, 4, "decisionTable_0_10", "1", "3", "pass", "ReturnedValueExpectation", null, null, "wow"); } private static final String SLIM_SCENARIO_TABLE = "!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" + "|${requestParam}|\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))); 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", "pass", "ConstructionExpectation", null, null, "fitnesse.slim.test.TestSlim"); checkExpectation(instructionList, 1, "decisionTable_2_0/scriptTable_0_0", "3", "1", "pass", "ReturnedValueExpectation", null, null, "1"); checkExpectation(instructionList, 2, "decisionTable_2_1/scriptTable_0_0", "3", "1", "pass", "ReturnedValueExpectation", null, null, "2"); } private void assertInstructionResultsOfSlimScenarioAreCorrect(NodeList instructionList) throws Exception { String instructionResults[] = {"pass", "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 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.contains(content)); } 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 == null && content == null) || result.contains(content)); } 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")); } } public static class JunitTestUtilities { public static Document getXmlDocumentFromResults(String results) throws Exception { String endOfXml = "</testsuite>"; 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); } } }