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. Shortcuts through the DOM
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.
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”.
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.