Test an XSL stylesheet in isolation

Một phần của tài liệu Manning JUnit recipes practical methods for program (Trang 670 - 676)

Solution

We have taken the solution that we presented in recipe 9.6, “Test an XSL stylesheet in isolation,” and expanded and refactored it. We added two tests: one for the case of one item in the shopcart and another for the case of three items in the shopcart. In the process, we decided to verify the content of the shopcart using plain XPath, rather than XMLUnit. Here is the entire test case class, fol- lowed by the reasoning behind our approach.

package junit.cookbook.coffee.presentation.xsl.test;

import java.io.FileInputStream;

import java.io.StringReader;

import javax.xml.transform.*;

import javax.xml.transform.stream.StreamSource;

import junit.cookbook.coffee.display.ShopcartItemBean;

import org.apache.xpath.XPathAPI;

B

Listing A.5 DisplayShopcartXslTest

640 APPENDIX A Complete solutions

import org.custommonkey.xmlunit.Transform;

import org.custommonkey.xmlunit.XMLTestCase;

import org.w3c.dom.*;

import com.diasparsoftware.java.util.Money;

public class DisplayShopcartXslTest extends XMLTestCase { private String displayShopcartXslFilename =

"../CoffeeShopWeb/Web Content/WEB-INF"

+ "/style/displayShopcart.xsl";

private Source displayShopcartXsl;

protected void setUp() throws Exception { displayShopcartXsl =

new StreamSource(

new FileInputStream(displayShopcartXslFilename));

}

public void testEmpty() throws Exception { String shopcartXmlAsString =

"<?xml version=\"1.0\" ?>"

+ "<shopcart>"

+ "<subtotal>$0.00</subtotal>"

+ "</shopcart>";

Document displayShopcartDom =

doDisplayShopcartTransformation(shopcartXmlAsString);

assertShopcartTableExists(displayShopcartDom);

assertSubtotalEquals("$0.00", displayShopcartDom);

assertXpathNotExists(

"//tr[@class='shopcartItem']", displayShopcartDom);

}

public void testOneItem() throws Exception { String shopcartXmlAsString =

"<?xml version=\"1.0\" ?>"

+ "<shopcart>"

+ "<item id=\"762\">"

+ "<name>Special Blend</name>"

+ "<quantity>1</quantity>"

+ "<unit-price>$7.25</unit-price>"

+ "<total-price>$7.25</total-price>"

+ "</item>"

+ "<subtotal>$7.25</subtotal>"

+ "</shopcart>";

Document displayShopcartDom =

doDisplayShopcartTransformation(shopcartXmlAsString);

assertShopcartTableExists(displayShopcartDom);

assertSubtotalEquals("$7.25", displayShopcartDom);

TE AM FL Y

Team-Fly®

641 Test an XSL stylesheet in isolation

assertShopcartItemAtRowIndexEquals(

new ShopcartItemBean(

"Special Blend", "762",

1,

Money.dollars(7, 25)), displayShopcartDom, 1);

}

public void testThreeItems() throws Exception {

// NOTE: Be sure to put line breaks after each <item>

// tag to avoid overstepping the limit for characters // on a single line.

String shopcartXmlAsString = "<?xml version=\"1.0\" ?>"

+ "<shopcart>\n"

+ "<item id=\"762\">"

+ "<name>Special Blend</name>"

+ "<quantity>1</quantity>"

+ "<unit-price>$7.25</unit-price>"

+ "<total-price>$7.25</total-price>"

+ "</item>\n"

+ "<item id=\"001\">"

+ "<name>Short</name>"

+ "<quantity>2</quantity>"

+ "<unit-price>$6.50</unit-price>"

+ "<total-price>$13.00</total-price>"

+ "</item>\n"

+ "<item id=\"803\">"

+ "<name>Colombiano</name>"

+ "<quantity>4</quantity>"

+ "<unit-price>$8.00</unit-price>"

+ "<total-price>$32.00</total-price>"

+ "</item>\n"

+ "<subtotal>$52.25</subtotal>"

+ "</shopcart>";

Document displayShopcartDom =

doDisplayShopcartTransformation(shopcartXmlAsString);

assertShopcartTableExists(displayShopcartDom);

assertSubtotalEquals("$52.25", displayShopcartDom);

assertShopcartItemAtRowIndexEquals(

new ShopcartItemBean(

"Special Blend", "762",

1,

Money.dollars(7, 25)), displayShopcartDom, 1);

642 APPENDIX A Complete solutions

assertShopcartItemAtRowIndexEquals(

new ShopcartItemBean(

"Short", "001", 2,

Money.dollars(6, 50)), displayShopcartDom, 2);

assertShopcartItemAtRowIndexEquals(

new ShopcartItemBean(

"Colombiano", "803", 4,

Money.dollars(8, 0)), displayShopcartDom, 3);

}

public void assertSubtotalEquals(

String expectedSubtotal, Document displayShopcartDom) throws TransformerException { assertXpathEvaluatesTo(

expectedSubtotal,

"//table[@name='shopcart']//td[@id='subtotal']", displayShopcartDom);

}

public void assertShopcartTableExists(

Document displayShopcartDom) throws TransformerException { assertXpathExists(

"//table[@name='shopcart']", displayShopcartDom);

}

public void assertShopcartItemAtRowIndexEquals(

ShopcartItemBean expectedShopcartItemBean, Document displayShopcartDom,

int rowIndex)

throws TransformerException { Node productIdAttributeNode = XPathAPI.selectSingleNode(

displayShopcartDom,

"//tr[@class='shopcartItem']["

+ rowIndex + "]/@id"); B

assertNotNull(

643 Test an XSL stylesheet in isolation

"Cannot find product ID at row index " + rowIndex, productIdAttributeNode);

String productId =

((Attr) productIdAttributeNode).getValue();

NodeList columnNodes = XPathAPI.selectNodeList(

displayShopcartDom,

"//tr[@class='shopcartItem']["

+ rowIndex + "]/td");

String actualCoffeeName =

getTextAtNode(columnNodes.item(0));

String actualQuantityAsString = getTextAtNode(columnNodes.item(1));

String actualUnitPriceAsString =

getTextAtNode(columnNodes.item(2));

ShopcartItemBean actualShopcartItemBean = new ShopcartItemBean(

actualCoffeeName, productId, Integer.parseInt(

actualQuantityAsString), Money.parse(

actualUnitPriceAsString));

assertEquals(

"Wrong shopcart item in row #" + rowIndex, expectedShopcartItemBean,

actualShopcartItemBean); D

}

public String getTextAtNode(Node tableDataNode) { return tableDataNode.getFirstChild().getNodeValue();

}

public Document doDisplayShopcartTransformation(

String shopcartXmlAsString) throws

TransformerConfigurationException, TransformerException {

Source shopcartXml = new StreamSource(

new StringReader(shopcartXmlAsString));

Transform transform =

new Transform(shopcartXml, displayShopcartXsl);

return transform.getResultDocument();

} }

C

644 APPENDIX A Complete solutions

Because the coffee product ID is not something we want to display to the end user, but is something we want to verify, we need to include it in the table row as the table row’s ID.

Rather than write four separate assertions for the information in the four col- umns, we use plain XPath to retrieve the table data cells in this table row and cre- ate a ShopcartItemBean from the data we display on the page.

This is the simpler assertion we can make as a result of the previous design deci- sion. The alternative was to invoke assertXpathEvaluatesTo() for each column in the row. We did not like the resulting duplication, which is the reason for our design choice.

For completion, listing A.6 shows an XSL stylesheet that passes these tests.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0"

xmlns:xalan="http://xml.apache.org/xslt">

<xsl:template match="/">

<html>

<head>

<meta http-equiv="Content-Type"

content="text/html; charset=ISO-8859-1" />

<meta name="GENERATOR" content="IBM WebSphere Studio" />

<meta http-equiv="Content-Style-Type" content="text/css" />

<link href="theme/Master.css" rel="stylesheet" type="text/css" />

<title>Your Shopcart</title>

</head>

<body>

<xsl:apply-templates />

</body>

</html>

</xsl:template>

<xsl:template match="shopcart">

<h1>your shopcart contains</h1>

<table name="shopcart" border="1">

<thead>

<tr>

<th>Name</th>

<th>Quantity</th>

<th>Unit Price</th>

<th>Total Price</th>

</tr>

Listing A.6 XSL stylesheet for displaying a shopcart

B

C

D

645 Validate XML documents in your tests

</thead>

<tbody>

<xsl:apply-templates />

<tr>

<td colspan="3">Subtotal</td>

<td class="subtotal" id="subtotal">

<xsl:value-of select="subtotal" />

</td>

</tr>

</tbody>

</table>

<form action="coffee" method="POST"><input type="submit"

name="browseCatalog" value="Buy More Coffee!" /></form>

</xsl:template>

<xsl:template match="item">

<tr class="shopcartItem" id="{@id}">

<td><xsl:value-of select="name" /></td>

<td><xsl:value-of select="quantity" /></td>

<td><xsl:value-of select="unit-price" /></td>

<td><xsl:value-of select="total-price" /></td>

</tr>

</xsl:template>

</xsl:stylesheet>

Even for such a relatively simple web page we have had to write approximately 100 lines of custom assertions and XML parsing code to implement our tests. It would likely be less effort to switch to HtmlUnit at this point, as we describe in recipe 12.10, “Verify web page content without a web server.”

Một phần của tài liệu Manning JUnit recipes practical methods for program (Trang 670 - 676)

Tải bản đầy đủ (PDF)

(753 trang)