Test entire Web applications with HttpUnit

While JUnit itself can test server-side Java code by writing test harnesses for individual classes, HttpUnit extends JUnit to test the integration over the Web by emulating the way a Web browser works and working through a Web server. This article will explain how you can take advantage of HttpUnit.
One great aspect of HttpUnit is that it can test entire Web applications, not just single pages. Because it honors form information and cookies, you can write tests to cover a whole session. For example, if your Web application includes a shopping cart, you could write a test to try logging in, selecting an item, placing it the shopping cart, and checking out. Since the tests are written in Java, there's no limit to how in-depth your tests can be. Let’s get started by looking at a simple HttpUnit test.
Making a request
Since HttpUnit can emulate an entire session and not just a single request, the
system uses a class, called WebConversation, to manage the requests,
handle the cookies, and resolve relative URLs. As you write more complicated
tests, the WebConversation class will become more important. In Listing A, the class simply creates a request to the URL
base_url. The response from this request is stored, and the JUnit method
assertEquals() tests whether the response was 200, which is the HTTP
response for a successful request.
Parsing a response
Once you’ve made a successful request to a Web server, it's time to parse the
result of the request. HttpUnit makes use of the JTidy package, which is included in
the HttpUnit distribution, to parse the resulting HTML into a Document Object
Model (DOM) tree. For those who aren’t familiar with DOM trees, they offer a
uniform way to manipulate a document in a hierarchical data structure. JTidy
provides a standardized way to manipulate the HTML result.
Listing B shows how to navigate the DOM tree and look for
specific text in the result. Our example first prints out the DOM tree and then
looks to see if an option is present in an HTML form. In this case, it is
looking to see if the option "JSP Book" is present from the Shopping Cart
example that ships with Tomcat.
Using the DOM is the only way to find specific text within a document tree.
You
should note, however, that the DOM tree that JTidy builds represents the
structure that a document should have, not necessarily what it does have. That
means that JTidy may add structural elements to the document tree that aren’t in
the HTML source but should be. That includes head and body markers, paragraph
marks, font tags, and more. Iterating through a DOM tree and visualizing the
output, as Listing B does, can be helpful. Listing C shows the output of SimpleDOM in Listing
B.
As you can see from Listing B, navigating through the DOM can be difficult and time-consuming. Fortunately, HttpUnit includes tools to make quick work of dealing with some HTML elements. In Listing D, we’ve accomplished the same task by asking the WebResponse object to return a list of WebForm objects. We select the first WebForm and then check whether the option “JSP Book” exists in the selectable list “item”. HttpUnit contains similar shortcuts for navigating the DOM tree for forms and tables.
Navigating links
HttpUnit offers much more than just parsing the result of a single connection.
The real power comes from being able to make multiple requests through the
WebConnection object. The easiest way to make multiple requests is by
following HTML links. In Listing E, we have a simple client that follows the first
link that says “Execute”.
Posting forms
By far, the most common use of HttpUnit is to test the results of filling out a
form. When we combine the uses of the previous examples, we can test to see if
filling out a form has the desired effect. The WebConversation object
takes care of making sure that all the links go to the correct endpoint and that
all cookies are honored through the session. In Listing F, we test a simple shopping cart by adding all
the items to the cart and printing out the results. Each request uses the same
WebConversation object, which ensures that the cookie values stay the
same, simulating an entire session. The output of the test will include all the
headers from the server so you can see that the cookies are being sent only once
by the server.
Listing F differs from the previous examples in its use of HTML forms. Rather
than just follow links, this example fills out each HTML form by using the
setParameter() method and submits it to the server, just as a real Web
browser would, right down to clicking the Submit button.
Now that you’ve
created test classes to parse HTML, follow links, and manipulate forms, you’re
ready to start creating test cases for your Web applications.