Jim Driscoll's Blog

Notes on Technology and the Web

Testing JSF

with 2 comments

It’s been a while since I’ve blogged last (ok, it’s been a year), but I recently came across a question that I have a little insight into, and I thought I’d tackle it briefly.

The question was simple:  “How do I test my JSF application?”

I’ve used two different test frameworks to do so, and besides being two of the most popular, they also offer a good example of the two different patterns used for Web testing.  The two programs are HTMLUnit and Selenium.  (Please note, there are certainly others –  FacesTester, and JSFUnit (which actually uses/extends HTMLUnit),  to name just two – but I’m going to stick to the two that I’ve used.)

HTMLUnit is a framework which uses browser simulation to test web pages – this means that no browser is launched, which also means that you can do things like test IE7 on Linux without a copy of Windows, as well as running testing in “headless mode”, meaning that you don’t even need a windowing system to be running (which is handy, and also very efficient for performance).  There are downsides to this, of course – for one, it’s possible that the simulation may not be perfect (though I’ve never found a case where it wasn’t).  The other disadvantage is that you can’t actually see what’s going on during testing, which can be awkward when figuring out why your test failed.    HTMLUnit supports emulating FF2, FF3, FF3.6, IE6, IE7, and IE8.

Selenium, on the other hand, uses browser automation – meaning that it’s actually using the browser you’re testing your web app in.  But that, in turn, means you’ll need different browsers installed to test – and in Windows, that means that you’ll also need multiple machines to test all the myriad versions of IE.  And since you’re running a browser in a windowing system, the machine requirements are also a little more substantial.  I’ve also found that configuring the browsers to be a bit tricky at times.  However, any inconvenience in setup is more than made up for by the Selenium IDE, which is really just a Firefox plugin that records mouse and keyboard actions for later playback.  Selenium supports automation of FF2, FF3, IE7, IE8, Safari2, and Safari3.

In both frameworks, you use their Java API to get a copy of a webpage, find components on that page (such as a button), and perform actions on those components (such as a click).  As such, the usage of both is pretty easy, and I’m not going to give a introductory tutorial of either.  (Selenium also offers a couple of other automation scripting methods in addition to Java, though I’ve never used them, so the topic is really much too big for a simple blog post.)

Which should you use?

I suspect that if you’re writing your first JSF test, Selenium is really the way to go, for one simple reason:  JSF id generation.  As I’m sure you know already, every HTML tag can have an id, and that id needs to be unique on that page.  For both APIs, the simplest way to find those tags within your code is to use the id.  There’s just one problem:  the id that’s in the generated HTML may be quite different from the id you use in your JSF page.

Take this (simplified) example:

<h:form id="frm">
  <h:outputText id="out" value="#{whatever}">
</h:form>

Now, say you wish to read the contents of the outputText…  What id would you use?  Answer:  “frm:out”.  Because templating can be used to insert one page into another, and all id’s need to be unique on the page, JSF has the idea of a “naming container” – every component inside a naming container has its naming container id prepended to the id of the component itself.  A form is one such naming container, but there are many more.

Now, it’s generally possible to figure out what the id will be (though not always easy, given some component libraries), so probably the easiest way to find the component’s id would be to use the Selenium IDE, and use it to find the id’s of the generated code.  The other ways to do this would be to use View Source on your browser, or dump the page contents in the Java code that you’re creating to System.out, and examine it that way.

Other factors may influence your decision, of course.  HTMLUnit has much better support for Ajax, Selenium has (somewhat feeble) support for Webkit based browsers, while HTMLUnit has none.

Anyhow, as I mentioned, I’m hardly an expert in this area, but I thought I knew enough to at least be helpful to the novice.  If you’re not a novice, and you’ve got any additional comments (such as corrections or additional frameworks that folks should check out), please comment…

Written by jamesgdriscoll

January 22, 2011 at 1:09 PM

Posted in JSF

2 Responses

Subscribe to comments with RSS.

  1. I had a similar need when doing Tapestry, and now SpringMVC. I wrote my own FunctionalTester based on the HORRIBLE tester in Tapestry 4. The big difference compared to HTMLUnit was that I wrote my api to what a user would see, not the browser. The second diff was that my tests all run in process. No external server needed. A typical test was like…

    Response resp = ft.createRequest(“/url/url”).submit();
    Request req = resp.createRequestForForm();
    req.setParameterForLabel(“First Name”, “Bob”);
    req.clickButtonByLabel(“Save”);
    resp = req.submit();

    Partially this was because I was trying to stay in the Tapestry world, even though I ended up basically rewriting what was there. And partially it was that I didn’t know about HTMLUnit until much too late. If I have some time in my next couple releases, I might take another look at HTMLUnit, to see if I can make it do what I need.

    Scott Carlson

    January 22, 2011 at 4:55 PM

    • We also used JUnit mock objects for some JSF testing, but for finding bugs, there’s no substitute for actually running the code on a server. Given what you’ve already done, I think you’re really going to love HTMLUnit… It’s really a pretty darn good API, though the overview docs could be better, the API docs (and the API design itself) is pretty straightforward.

      jamesgdriscoll

      January 25, 2011 at 11:50 PM


Leave a comment