Use CSS Selectors with HtmlUnit

Posted by kerry on Gooder Code See other posts from Gooder Code or by kerry
Published on Mon, 31 Jan 2011 21:33:20 +0000 Indexed on 2011/01/31 23:32 UTC
Read the original article Hit count: 333

Filed under:

HtmlUnit is a great library for performing web integration tests in Java.  But sometimes node traversal can be somewhat cumbersome. Fear not fellow automated tester (good for you!).  I found a great little project on Github that will allow you to query your document for elements via css selectors similar to jQuery.

The project is located at https://github.com/chrsan/css-selectors.  You can use Maven to build it, or download 1.0.2 here.  Beware.  I will not be updating this link so I suggest you download the latest code.

In any case, you can use it like so:

    // from HtmlUnit getting started
    final WebClient webClient = new WebClient();
    final HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
    final DOMNodeSelector cssSelector = new DOMNodeSelector(page.getDocumentElement());
    final Set elements = cssSelector.querySelectorAll("div.section h2");
    final Node first = elements.iterator().next();

    assertThat(first.getTextContent(), equalTo("HtmlUnit"));

The only problem here is that the querySelectAll returns a Set<Node>.  Not HtmlElement like we may want in some cases.   However, if you were to reflect on the Set, you would find that it is indeed a Set of HtmlElement objects.

Typically, I like to create a base class for my web tests.  Just for fun, I am using the $ method similar to jQuery.

public class WebTestBase {

    protected WebClient webClient;

    protected HtmlPage htmlPage;

    protected void goTo(final String url){
        return (HtmlPage)webClient.getPage(url);
    }

    protected List $(final String cssSelector) {

        final DOMNodeSelector cssSelector = new DOMNodeSelector(htmlPage.getDocumentElement());
        final Set nodes = cssSelector.querySelectorAll("div.section h2");

        // for some reason Set cannot be cast to Set?
        final List elements = new ArrayList(nodes.size());
        for (final Node node : nodes) {
            elements.add((HtmlElement)node);
        }

        return elements;
    }
}

Now we can write tests like this:

public class LoginWebTest extends WebTestBase {

    @Test
    public void login_page_has_instructions() throws Exception {

        goTo(baseUrl + "/login")

        assertThat( $("p.instructions").size(), equalTo(1) );
    }

}

© Gooder Code or respective owner

Related posts about Developer Tools