HttpUnit Cookbook

Here is a brief description of how you can use HttpUnit with JUnit to test your own web sites.

Obtaining a web page response

The center of HttpUnit is the WebConversation class, which takes the place of a browser talking to a single site. It is responsible for maintaining session context, which it does via cookies returned by the server. To use it, one must create a request and ask the WebConversation for a response.
For example:
    WebConversation wc = new WebConversation;
    WebRequest     req = new GetMethodWebRequest( "http://www.meterware.com/testpage.html" );
    WebResponse   resp = wc.getResponse( req );
The response may now be manipulated either as pure text (via the toString() method), as a DOM (via the getDOM() method), or by using the various other methods described below.

Using the table structure of a web page

Many web designers make heavy use of tables to control the page formatting. You can take advantage of this by looking at the tables in the page as discrete elements. The :getTables() method will return an array of the top-level tables in the page (that is, those which are not nested within other tables), in the order in which they appear in the document. Given a table, you can ask for one of its cells, and treat the result either as text or a DOM or ask for and tables, links, or forms nested within it. For example, the following code will confirm that the first table in the page has 4 rows and 3 columns, and that there is a single link in the last cell of the first row:
    WebTable table = resp.getTables()[0];
    assertEquals( "rows", 4, table.getRowCount() );
    assertEquals( "columns", 3, table.getColumnCount() );
    assertEquals( "links", 1, table.getTableCell( 0, 2 ).getLinks().length );
In most cases, the purpose of a test is to verify the text, rather than the formatting. HttpUnit provides shortcuts to do this. For example, imagine that the second table in the page should look like this:
NameColor
gulesred
sableblack

The following JUnit code will verify it:


    String[][] colors = resp.getTables()[1].asText();
    assertEquals( "Name",  colors[0][0] );
    assertEquals( "Color", colors[0][1] );
    assertEquals( "gules", colors[1][0] );
    assertEquals( "red",   colors[1][1] );
    assertEquals( "sable", colors[2][0] );
    assertEquals( "black", colors[2][1] );
Note that the asText() method, used to convert an entire table into an array of String ignores all formatting tags. At times, entire rows or columns of a table may be used for appearance purposes only. You can ignore rows or columns consisting only of images or empty tags by invoking purgeEmptyCells on the table. In many cases, tables begin with some fixed text and the purpose of the test is to verify the dynamic portion. As a general rule, the first cell will contain something fixed and you can search for it - even if the table is nested inside other tables. Thus, the above table could have been found with:
String[][] colors = resp.getTableStartingWith( "Name" );
which has the advantage of being immune to many page formatting changes which might make it the third or fourth table.

Working with forms

A dynamic web site tends to have many html forms, each of which contains various kinds of controls: text boxes, pull-down menus, radio buttons, and so on. The HTML for these controls vary widely; however, the intent is roughly the same, so HttpUnit makes them look the same.

There are a few basic things that a tester is likely to want to do with a form. The most obvious first step is to verify the controls and their default values; if they are correct, the tester will generally make some changes and submit the form to see how the system responds. HttpUnit makes both tasks easy.

The examples below assume the following form definition:

Restaurant Name:
Restaurant Type: Chinese Tex/Mex Italian
Location:
Accepts Credit Cards

The default values may be checked as follows:
    WebForm form = resp.getForms()[0];      // select the first form in the page
    assertEquals( "La Cerentolla", form.getParameterValue( "Name" ) );
    assertEquals( "Chinese",       form.getParameterValue( "Food" ) );
    assertEquals( "Manayunk",      form.getParameterValue( "Location" ) );
    assertEquals( "on",            form.getParameterValue( "CreditCard" ) );
Note that all controls are treated alike, with the exception of the checkbox.

Simulating the submission of the form will involve asking the WebConversation for a response to a request which was defined by the form, possibly modifying the form parameters beforehand. For example, to correct the restaurant type and indicate that it does not accept credit cards:

    request = form.getRequest();
    request.setParameter( "Food", "Italian" );
    request.removeParameter( "CreditCard" );
    response = wc.getResponse( request );
And of course the test would then proceed to examine the response to this submission as well.