Skip to content
Snippets Groups Projects
Commit 1b8a6f2d authored by Goik Martin's avatar Goik Martin
Browse files

Testing duplicate handler execution

parent 286649db
No related branches found
No related tags found
No related merge requests found
package de.hdm_stuttgart.de.sda1.saxhtml.v1.test;
import org.junit.Assert;
import org.junit.Test;
import de.hdm_stuttgart.de.testing.dom.ConversionTest;
import de.hdm_stuttgart.de.testing.dom.DomAssert;
import de.hdm_stuttgart.mi.sda1.saxhtml.v1.Memo2HtmlHandler;
/**
* Unit testing XML to HTML output
*/
@SuppressWarnings("javadoc")
public class TestSimpleSaxTransform extends ConversionTest {
public TestSimpleSaxTransform() {
super("src/main/resources/memo.xml", new Memo2HtmlHandler(), ".1.html");
}
@Test public void checkWellFormedness() {
Assert.assertNull("Unable to parse generated file:" + errorInitString, errorInitString);
}
@Test public void testSenderInHeader() {
DomAssert.assertSingleNodeContent("<title>Memo message</title> must be the only child of <head>", htmlRootElement, "head/*", "title", "Memo message");
}
@Test public void testFrom() {
DomAssert.assertSingleNodeContent("<strong>M. Goik</strong> must appear within first <h2> child of <body>",
htmlRootElement, "body/h2[1]/strong", "strong", "M. Goik");
}
@Test public void testNumberfRecipients() {
DomAssert.assertNumberOfNodes("Two <li> elements required matching two recipients", htmlRootElement, "body/ul/li", 2);
}
@Test public void testSecondRecipient() {
DomAssert.assertSingleNodeContent("Second recipient must be <li>A. June</li>",
htmlRootElement, "body/ul/li[2]", "li", "A. June");
}
@Test public void testSubject() {
DomAssert.assertSingleNodeContent("<h2>Subject: Best wishes</h2> must appear as first child of <body>",
htmlRootElement, "body/*[4]", "h2", "Subject: Best wishes");
}
@Test public void testContent() {
DomAssert.assertSingleNodeContent("Last child of <body> must be content",
htmlRootElement, "body/*[5]", "p", "Hi all, congratulations to your splendid party");
}
}
\ No newline at end of file
package de.hdm_stuttgart.de.sda1.saxhtml.v2.test;
import org.junit.Test;
import de.hdm_stuttgart.de.testing.dom.ConversionTest;
import de.hdm_stuttgart.de.testing.dom.DomAssert;
import de.hdm_stuttgart.mi.sda1.saxhtml.v2.Memo2HtmlHandler;
/**
* Turning &lt;memo&gt; documents to HTML as being shown in sample document memo.xml.2.sample.html
*/
@SuppressWarnings("javadoc")
public class TestComplexSaxTransform extends ConversionTest {
public TestComplexSaxTransform() {
super("src/main/resources/memo.xml", new Memo2HtmlHandler(), ".2.html");
}
@Test public void testSenderInHeader() {
DomAssert.assertSingleNodeContent("<title>Memo from M. Goik</title> must be child of <head>", htmlRootElement, "head/title", "Memo from M. Goik");
}
@Test public void testNumberfRecipients() {
DomAssert.assertNumberOfNodes("There should be two <li> elements matching two recipients", htmlRootElement, "body/dl/dd/ul/li", 2);
}
@Test public void testH1MemoSubjectMessage() {
DomAssert.assertSingleNodeContent("<h2>Subject:Best wishes</h2> must appear as first child of <body>",
htmlRootElement, "body/*[1]", "h2", "Subject:Best wishes");
}
@Test public void testSenderBeforeRecipientList() {
DomAssert.assertSingleNodeContent("<dd>M. Goik</dd> must appear as second child of the list of recipients",
htmlRootElement, "body/dl/*[2]", "dd", "M. Goik");
}
@Test public void testMemoContent() {
DomAssert.assertSingleNodeContent("content must appear as second <p> child after recipient list in <body>",
htmlRootElement, "body/dl/following-sibling::*[2]", "p", "Hi all, congratulations to your splendid party");
}
@Test public void testLastParagraph() {
DomAssert.assertNumberOfNodes("Expecting two <p> children of <body>",
htmlRootElement, "body/*[name(.)='p']", 2);
}
@Test public void testSenderAtFoot() {
DomAssert.assertSingleNodeContent("<strong>M. Goik</strong> must appear inside a <p> immediately following the list of recipients",
htmlRootElement, "body/dl/following-sibling::*[1]", "h2", "Subject: Best wishes");
}
}
\ No newline at end of file
package de.hdm_stuttgart.de.testing.dom;
/**
* @author goik
*
*/
public class AssertXpathResult extends AssertionError {
private static final long serialVersionUID = -1369600480719379445L;
/**
* @param msg
*/
public AssertXpathResult(String msg) {
super(msg);
}
}
package de.hdm_stuttgart.de.testing.dom;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import javax.xml.parsers.ParserConfigurationException;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.xml.sax.SAXException;
import de.hdm_stuttgart.mi.sda1.saxhtml.tools.ContentRedirect;
import de.hdm_stuttgart.mi.sda1.saxhtml.v1.Memo2Html;
/**
* Turning &lt;memo&gt; documents to HTML as being shown in sample document memo.xml.2.sample.html
*/
@SuppressWarnings("javadoc")
public abstract class ConversionTest {
public final String xmlInputFileName, htmlOutputFileName;
final ContentRedirect saxHandler;
protected String errorInitString = null;
protected Element htmlRootElement;
protected ConversionTest(final String xmlInputFileName, final ContentRedirect saxHandler, final String outputExtension) {
this.saxHandler = saxHandler;
this.xmlInputFileName = xmlInputFileName;
this.htmlOutputFileName = xmlInputFileName + outputExtension;
final PrintStream out;
try {
out = new PrintStream(htmlOutputFileName);
} catch (FileNotFoundException e1) {
errorInitString = "Unable to open file '" + htmlOutputFileName + "' for writing";
return;
}
saxHandler.setOutputStream(out);
final Memo2Html memo2html;
try {
memo2html = new Memo2Html(saxHandler);
} catch (SAXException | ParserConfigurationException e2) {
e2.printStackTrace();
return;
}
try {
memo2html.parse(xmlInputFileName);
} catch (IOException e1) {
errorInitString = "Unable parse file '" + xmlInputFileName + "'";
return;
} catch (SAXException e) {
e.printStackTrace();
}
final SAXBuilder parser = new SAXBuilder();
try {
htmlRootElement = parser.build(htmlOutputFileName).getRootElement();
} catch (JDOMException | IOException e1) {
errorInitString = "Unable to parse file '" + htmlOutputFileName + "', see stack trace for further information";
e1.printStackTrace();
}
out.close();
}
}
\ No newline at end of file
package de.hdm_stuttgart.de.testing.dom;
import java.util.List;
import org.jdom2.Element;
import org.jdom2.xpath.XPathExpression;
import org.jdom2.xpath.XPathFactory;
/**
* @author goik
*
*/
public class DomAssert {
final static XPathFactory xpf = XPathFactory.instance();
/**
* @param msg
* @param context
* @param xpath
* @param expectedNodeCount
*/
public static void assertNumberOfNodes(final String msg, final Element context, final String xpath, int expectedNodeCount) {
@SuppressWarnings({ "unchecked", "rawtypes" })
final XPathExpression<Element> xpathExpr = (XPathExpression<Element>) (XPathExpression) xpf.compile(xpath);
final List<Element> matchedNodes = xpathExpr.evaluate(context);
if (expectedNodeCount != matchedNodes.size()) {
throw new AssertXpathResult(msg + "\nExpected " + expectedNodeCount + " node" + (expectedNodeCount == 1? "":"s") + " for xpath '" + xpath +
"' but found " + matchedNodes.size());
}
}
/**
* @param msg
* @param context
* @param xpath
* @param expectedContent
*/
public static void assertSingleNodeContent(final String msg, final Element context, final String xpath, String expectedContent) {
@SuppressWarnings({ "unchecked", "rawtypes" })
final XPathExpression<Element> xpathExpr = (XPathExpression<Element>) (XPathExpression) xpf.compile(xpath);
final List<Element> matchedNodes = xpathExpr.evaluate(context);
if (1 == matchedNodes.size()) {
final String content = matchedNodes.get(0).getValue();
if (!content.equals(expectedContent)) {
throw new AssertXpathResult(msg + "\nExpected content '" + expectedContent + "' for xpath '" + xpath + "' but found '" + content + "'");
}
} else {
throw new AssertXpathResult("\nExactly one node expected for xpath '" + xpath + "' but found " + matchedNodes.size());
}
}
/**
* @param msg
* @param context
* @param xpath
* @param expectedTagName
* @param expectedContent
*/
public static void assertSingleNodeContent(final String msg, final Element context, final String xpath, final String expectedTagName, String expectedContent) {
@SuppressWarnings({ "unchecked", "rawtypes" })
final XPathExpression<Element> xpathExpr = (XPathExpression<Element>) (XPathExpression) xpf.compile(xpath);
final List<Element> matchedNodes = xpathExpr.evaluate(context);
if (1 == matchedNodes.size()) {
final Element element = matchedNodes.get(0);
final String elementTagName = element.getName();
if (!expectedTagName.equals(elementTagName)) {
throw new AssertXpathResult(msg + "\nExpected <" + expectedTagName + "> for xpath '" + xpath + "' but found <" +
elementTagName + ">");
}
final String content = element.getValue();
if (!expectedContent.equals(content)) {
throw new AssertXpathResult(msg + "\nExpected element content '" + expectedContent + "' for xpath '" + xpath + "' but found '" +
content + "'");
}
} else {
throw new AssertXpathResult("Exactly node expected for xpath '" + xpath + "' but found " + matchedNodes.size());
}
}
}
......@@ -6,50 +6,32 @@
</head>
<body><h2>Objective</h2><p>Implementing two SAX based Java applications
transforming memo documents to HTML.</p><h2>Preparations</h2><ol>
transforming memo documents to HTML.</p><h2>Preparations /
Description</h2><ol>
<li>Download <a
href="/iliasData/goik/sax_hahHzh66-99DDDwsq/saxmemo2html.zip">saxmemo2html.zip</a>
and import it as a project into your Eclipse workspace.</li>
<li><p>Your resulting Project <code>saxmemo2html</code>contains among
other files:</p><ul>
<li><p><strong>src/main/resources/memo.xml</strong></p><p>A sample
memo input document.</p></li>
<li><p><strong>de.hdm_stuttgart.mi.sda1.saxhtml.v1.Memo2HtmlHandler</strong></p><p>A
SAX event handler which currently just creates static
<code>&lt;html&gt;&lt;/html&gt;</code> output. The non-default
constructor expects a <a
href="http://docs.oracle.com/javase/8/docs/api/java/io/PrintStream.html">java.io.PrintStream</a>
allowing unit tests to redirect output to a file for subsequent
result analysis.</p></li>
<li><p><strong>de.hdm_stuttgart.mi.sda1.saxhtml.v1.Driver</strong></p><p>Executing
this class converts <code>memo.xml</code> to
<code>src/main/resources/memo.xml.1.html</code> by using
<code>de.hdm_stuttgart.mi.sda1.saxhtml.v1.Memo2HtmlHandler</code>
and writing to output console.</p></li>
<li><p><strong>src/main/resources/memo.xml.1.sample.html</strong></p><p>The
intended output corresponding to be generated from </p></li>
<li><p><strong>de.hdm_stuttgart.de.sda1.saxhtml.v1.test.TestSimpleSaxTransform</strong></p><p>This
Junit class executes your handler and writes the corresponding
output to src/main/resources/memo.xml.1.html. The latter file then
becomes subject to a series of XPath expression tests checking for
correctness of your output.</p></li>
</ul></li>
</ol><h2>Description</h2><p>Our sample document memo document
contains:</p><pre style="font-family:monospace;">&lt;memo&gt;
<li><p>Your imported project <code>saxmemo2html</code> contains:</p><ul>
<li><p><strong>src/main/resources/memo.xml, a sample memo input
document:</strong></p><pre style="font-family:monospace;">&lt;memo&gt;
&lt;from&gt;M. Goik&lt;/from&gt;
&lt;to&gt;B. King&lt;/to&gt;
&lt;to&gt;A. June&lt;/to&gt;
&lt;subject&gt;Best wishes&lt;/subject&gt;
&lt;content&gt;Hi all, congratulations to your splendid party&lt;/content&gt;
&lt;/memo&gt;</pre><h2>ToDo, Part 1</h2><p>This exercise deals with Java
classes from packages containing the string <strong>v1</strong> in their
names. Complete the implementation of <code>Memo2HtmlHandler</code> to
generate the content of <code>memo.xml.1.sample.html</code>:</p><pre>&lt;html&gt;
&lt;/memo&gt;</pre></li>
<li><p><strong>de.hdm_stuttgart.mi.sda1.saxhtml.v1.Memo2HtmlHandler</strong></p><p>A
SAX event handler currently just creating
'<code>&lt;html&gt;&lt;/html&gt;</code>' as output. The method
<code>setOutputStream(final PrintStream out)</code> allows for Junit
tests redirecting output to a file and subsequently analyzing the
result.</p></li>
<li><p><strong>src/main/resources/memo.xml.1.expected.html, the
intended output to be generated from
<code>memo.xml:</code></strong></p><pre>&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Memo message&lt;/title&gt;
&lt;/head&gt;
......@@ -63,19 +45,50 @@
&lt;h2&gt;Subject: Best wishes&lt;/h2&gt;
&lt;p&gt;Hi all, congratulations to your splendid party&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</pre><p>Your SAX handler shall allow for processing of multiple
XML input documents in sequence. </p><p>Watch your output being generated by
executing <code>de.hdm_stuttgart.mi.sda1.saxhtml.v1.Driver</code>. When you
are satisfied with your result execute the Junit test
<code>de.hdm_stuttgart.de.sda1.saxhtml.v1.test.ConversionTest</code>. When
you are finished export your Maven project as a compressed .zip archive and
upload it.</p><h2>ToDo, Part 2</h2><p>This second exercise deals with Java
classes from packages containing the string <strong>v2</strong> in their
names. So you might want to close <strong>all</strong> file tabs in your
current Eclipse project to avoid confusing yourself with files from the
first part of this exercise.</p><p>Your project contains a second set of
files intended to create more sophisticated output. A sample result is being
contained in <code>memo.xml.2.sample.html</code>:</p><pre>&lt;html&gt;
&lt;/html&gt;</pre><p>.</p></li>
<li><p><strong>de.hdm_stuttgart.de.sda1.saxhtml.v1.test.TestSimpleSaxTransform</strong></p><p>Running
this class as a Junit test in turn executes an instance of
<code>Memo2HtmlHandler</code> and writes the corresponding output to
<code>src/main/resources/memo.xml.1.html</code>. This output will
subsequently be duplicated to your eclipse's console as well. The
latter file then becomes subject to the series of XPath expression
tests checking your output for various aspects of
correctness.</p><h3 style="color:red;">Caution!</h3><ul>
<li><p>When implementing your SAX handler <b>always</b> use the
predefined output stream <code>private PrintStream out</code> in
class <code>Memo2HtmlHandler</code> which will direct your
output to <code>memo.xml.1.html</code>. In contrast calls using
System.out.println(...) will only create text on standard output
i.e. in your (Eclipse's) console but not in
<code>memo.xml.1.html</code>.</p></li>
<li>Test execution requires your Xhtml output to be well-formed.
In case of doubt inspect the generated file
<code>src/main/resources/memo.xml.1.html</code>.</li>
</ul></li>
</ul></li>
</ol><h2>ToDo, Part 1</h2><p>This exercise deals with Java classes from
packages containing the string <strong>v1</strong> in their names.</p><ol>
<li>Complete the implementation of
<code>de.hdm_stuttgart.mi.sda1.saxhtml.v1.Memo2HtmlHandler</code> to
generate output as in <code>memo.xml.1.sample.html</code>.</li>
<li>Your SAX handler shall allow for processing multiple XML input
documents in sequence. </li>
</ol><p>Watch your output being generated by executing the Junit test. On
completion export your Maven project as a compressed .zip archive (.tar.gz
export format may not work!) and upload it.</p><h3
style="color:red;">Caution:</h3><p>Marking will happen semi automatically
based on the Junit test results. Thus uploading projects containing Java
syntax errors or producing non well-formed Xhtml output is a waste of time
(your's and mine).</p><h2>ToDo, Part 2</h2><p>This second exercise deals
with Java classes from packages containing the string <strong>v2</strong> in
their names. So you might want to close <strong>all</strong> file tabs in
your current Eclipse project to avoid getting confused with the first part
of this exercise.</p><p>Your project contains a second set of files intended
to create more sophisticated output. The intended result is being contained
in <code>memo.xml.2.expected.html</code>:</p><pre>&lt;html&gt;
&lt;head&gt;&lt;title&gt;Memo from M. Goik&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;
&lt;h2&gt;Subject:Best wishes&lt;/h2&gt;
......@@ -95,17 +108,23 @@
&lt;p&gt;End of message from &lt;strong&gt;M. Goik&lt;/strong&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</pre><p>Complete the implementation of
<code>de.hdm_stuttgart.mi.sda1.saxhtml.v2.Memo2HtmlHandler</code>.
Corresponding Driver and Junit classes are being supplied as
<code>de.hdm_stuttgart.mi.sda1.saxhtml.v2.Driver</code> and
<code>de.hdm_stuttgart.de.sda1.saxhtml.v2.test.TestComplexSaxTransform</code>.</p><p>When
you are finished zip your project again and upload it. Only the last .zip
file will become subject to marking.</p><h3>Hint:</h3><p>In this second part
the order of content from your XML input is not being preserved. The subject
for example is to be shown before both sender and recipients. Furthermore
some input (sender's name) has to be shown multiple times. To tackle these
challenges you may first collect all relevant input during the SAX parsing
process and completely defer HTML output generation to the <a
href="http://docs.oracle.com/javase/8/docs/api/org/xml/sax/ContentHandler.html#endDocument--">endDocument()</a>
method.</p></body>
<code>de.hdm_stuttgart.mi.sda1.saxhtml.v2.Memo2HtmlHandler</code>. A
Corresponding Junit Test class is being provided by
<code>de.hdm_stuttgart.de.sda1.saxhtml.v2.test.TestComplexSaxTransform</code>.</p><p>O
completion export your project as a .zip file again and upload it. Only the
last project export file containing both projects will become subject to
marking.</p><h3>Hint:</h3><p>In this second part the order of content being
generated from <code>memo.xml</code> is not being preserved. The
<code>&lt;subject&gt;</code>'s content for example is to be shown before
both sender and recipients. Furthermore the sender's name being contained in
<code>&lt;from&gt;</code> has to be shown multiple times in different
positions. To tackle these challenges you may implement two distinct
processing phases:</p><ol>
<li>Collect all relevant input during the SAX parsing process by
providing appropriate containers.</li>
<li>Completely defer XHTML output generation to the <a
href="http://docs.oracle.com/javase/8/docs/api/org/xml/sax/ContentHandler.html#endDocument--">endDocument()</a>
method.</li>
</ol></body>
</html>
......@@ -41,6 +41,10 @@ public abstract class SaxFilterTest {
SaxFilterTest.htmlOutputFileName = xmlInputFileName + resultFileExtension;
SaxFilterTest.saxHandler = saxHandler;
processAndParseResult();
}
static protected void processAndParseResult() {
final PrintStream out;
try {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment