Integrating HttpUnit with XTest
Version: 0.3
Authors:
John Baker
Abstract: This document summarizes how to integrate HttpUnit with
XTest.
HttpUnit
is an Open Source functional test tool for testing web pages using
JavaTM. A test case that uses HttpUnit queries the WebServer and can
evaluate the responses it receives. For example, it's possible to retrieve
all the elements of an html page and write Java code to evaluate them.
Also, it's possible to mimic a user's actions, such as clicking on
an html link or button, entering some text in a textedit or choosing
an item from a dropdown listbox. Since HttpUnit test cases are written
in Java they can complement test cases written using Jemmy or Jelly.
JSPs can also be tested since a JSP is translated to a Servlet and Servlets
are compiled and executed by the Web Server which then outputs .html.
Servlets can also be tested if the Servlet extends HttpServlet and sets
some html content information - see the Servlet spec for more information.
How does HttpUnit work?
A test case written using HttpUnit is essentially a web client. If both
the WebClient and WebConversation classes are used then the test case
is like a web browser. These classes maintain the client's state which
includes cookies, URLs and frame sets. This allows a user to send requests
for specific html resources and retrieve the responses. The WebRequest
class represents a request to a remote or local (as in NetBean's case)
server. The WebResponse class encapsulates the reply. Here's part of
a simple example:
WebConversation conversation
= new WebConversation(); // create a new web client
WebResponse myresponse = conversation.getResponse(
"http://netbeans.org"
); //get the response from Web Server
System.out.println("The title of the page is " + myresponse.getTitle());
// output title of the page
For each request, the WebConversation class stores headers that are
sent to the web server. Cookies can also be stored. To set a header
for transmission to the server, use WebConversation's setHeaderField(String
fieldName, String fieldValue) method. For authorization headers use
the setAuthorization(String userName, String password) method. For cookies,
use getCookieNames() and getCookieValue()
methods. To add a cookie, use the
addCookie(String name, String value) method to add a cookie to
the list of cookies to send. For cookies that are defined by the server,
use getNewCookieNames() and getNewCookieValue().
Here's an example for printing all the new cookies set in a web server
response:
for (int i=0; i; cookieNames.length;i++) {
System.out.println(cookieNames[i] + " - ");
System.out.println(response.getNewCookieValue(cookieNames[i]));
}
HttpUnit has several methods for inspecting the response received,
such as getTitle().
Also, HttpUnit uses XML DOM to retrieve more information. It can view
the html document as a DOM. The way it uses DOM is by parsing the html
tags and ordering them as a tree structure representation using a parser
called JTidy. For more information about HttpUnit, see the References
at the bottom of this page.
Example Setup
1.Download httpunit.jar and Tidy.jar from
http://httpunit.sourceforge.net/
2.Copy downloaded jars to any suitable directory
3.Create a build scripts (build.xml and build-${testtype}.xml)
4.Create a configuration file (cfg-${testtype}.xml)
5.Create a properties file for URLs
6.Develop your HttpUnit test case
7.Start xtest using Ant from the commandline passing arguments for
the path to the NetBeans build and properties file
Requirements for setup files
build-${testtype}.xml - make sure you don't forget
add properties for the HttpUnit and Tidy jar files (please note,
directory.with.httpunit.jars
shoud be relative path from your build script location to the location
where downloaded jars are stored)
<property name="xtest.extra.jars.path" location="
directory.with.httpunit.jars" />
<property name="xtest.extra.jars" value="httpunit.jar;Tidy.jar"
/>
Properties File
Sample contents of properties file, urls.properties
xtest.userdata|url1=http://localhost:8081/ProductList.jsp
HttpUnit Test case
Sample HttpUnit testcase. This test case exercises a Web Application,
which had been deployed manually to Tomcat prior to running this test.
Alternatively, a test case could be added to the testbag which uses
Jemmy or Jelly to compile and deploy the Web Application.
import com.meterware.httpunit.*;
import org.netbeans.junit.NbTestSuite;
import org.netbeans.junit.Nbtestcase;
import junit.framework.*;
import org.netbeans.junit.*;
/**
* In this example, the test case will get a response from the Web Server for ProductList.jsp (HTML produced).
* The test case will connect to the URL and in the first page, add the first CD to the Shopping Cart,
* delete the CD that appears in the cart in ShopCart.jsp, click on the Resume Shopping button in the
* EmptyCart.jsp, then add the same CD again, but this time, click the Place Order button. In PlaceOrder.jsp,
* the Resume Shopping link is clicked and the test case returns to ProductList.jsp.
*
* @author John Baker
* @version 1.0
*/
public class TestCdShopCartWeb extends Nbtestcase{
/** URL of website */
private String url;
public TestCdShopCartWeb(String testName) {
super(testName);
}
/** Use for execution inside IDE */
public static void main(java.lang.String[] args) {
junit.textui.TestRunner.run(suite());
}
public static Test suite() {
TestSuite suite = new NbTestSuite(TestCdShopCartWeb.class);
System.out.println("Test started");
return suite;
}
public void testCdShopCartWeb() {
//HttpUnitOptions.setParserWarningsEnabled(true); // uncomment to enable warnings
url = System.getProperty("url1");
if(url==null) {
fail("Property url hasn't been set");
}
WebConversation conversation=null;
WebResponse response=null;
try {
/* Get the title of the first page. */
conversation = new WebConversation();
response = conversation.getResponse(url); // browse ProductList.jsp
WebForm form = response.getForms()[0];
assertTrue(response.getTitle().equals("CD Catalog List"));
// Get Table in ProductList.jsp and Add the 1st CD to the shopping cart
WebTable cdTable = response.getTables()[0];
TableCell cdCell = cdTable.getTableCell(1, 5); //get cell object, 2nd row, 6th column
WebForm addContainer = cdCell.getForms()[0];
WebRequest request = addContainer.getRequest();
response = conversation.getResponse( request );
// In ShopCart.jsp again
form = response.getForms()[0];
assertTrue(response.getTitle().equals("Shopping Cart"));
// Verify the name of the CD that was added to the Shopping Cart
cdTable = response.getTables()[0];
cdCell = cdTable.getTableCell(1, 1);
String cellStr = cdCell.asText();
assertTrue(cellStr.equals("Yuan"));
//Delete CD from cart in ShopCart.jsp
cdCell = cdTable.getTableCell(1, 3); //click on the Delete button in 2nd row, 4th column
addContainer = cdCell.getForms()[0];
request = addContainer.getRequest();
response = conversation.getResponse( request );
assertTrue(response.getTitle().equals("Empty Cart"));
WebForm resumeShopForm = response.getForms()[0]; // Resume Shopping
request = resumeShopForm.getRequest();
response = conversation.getResponse( request );
// Get Table in ProductList.jsp and Add the 1st CD to the shopping cart
cdTable = response.getTables()[0];
cdCell = cdTable.getTableCell(1, 5); //get cell object, 2nd row, 6th column
addContainer = cdCell.getForms()[0];
request = addContainer.getRequest();
response = conversation.getResponse( request );
// Forms in the ShopCart.jsp page - the first form, index 0 contains the table
resumeShopForm = response.getForms()[1]; // Resume Shopping (index 1 = 2nd form)
WebForm placeOrderForm = response.getForms()[2]; // Place Order
WebForm cancelOrderForm = response.getForms()[3]; // Cancel Order
// Place an order for the CD
request = placeOrderForm.getRequest();
response = conversation.getResponse( request );
//Check title of page
assertTrue(response.getTitle().equals("Place Order"));
WebForm resumeForm = response.getForms()[0];
// Click Resume Shopping button
request = resumeForm.getRequest();
response=conversation.getResponse(request);
assertTrue(response.getTitle().equals("CD Catalog List"));
} catch(Exception e) {
e.printStackTrace();
}
}
}
Execution from the Commandline
Example command:
% ant -Dxtest.testtype=web
-Dxtest.userdata.propertyfile="urls.properties"
Note: you can include
-Dnetbeans.home <your NetBeans install directory> in this
commandline.
Tips
- Use assertTrue to verify forms in a web page or after calling
getResponse(request)
- Use NetBean's debugger for more sophisticated debugging of test
cases
- You may have to initialize some HttpUnit's objects to null
- When coding your test case, at the end, return to the base state
References