Introducing Faces Tester
For the last month or so I have been working on a test framework for JavaServer Faces applications with my friend Jason Lee. The goal of this framework, named FacesTester, is to enable the test driving of JSF applications. Earlier Jason announced FacesTester and today I’d like to illustrate one very simple example of how FacesTester can be used to specify a simple web interaction in a test driven manner.
Following in the well trodden path of others let’s start by making a quick login page. Using FacesTester I can write a JUnit test like the following that describes how I want this simple page to work:
public class WhenClickingTheLoginButton {
@Test
public void shouldDisplayGreetingToUserNamedInUsernameField() {
FacesTester tester = new FacesTester();
FacesPage page = tester.requestPage("/login.xhtml");
FacesForm form = page.getFormById("form");
form.setValue("username", "Rod");
form.submit("login");
assertThat(page.getComponentWithId("greeting").getValueAsString(), is("Hello, Rod!"));
}
}
As you can see this test specifies that if a user types in their username and clicks the login button then they should receive a friendly greeting from the system. This test fails when run since we haven’t written any production code yet. The message we get is:
com.steeplesoft.jsf.facestester.FacesTesterException: The page /login.xhtml was not found.
So let’s create a simple HTML to pass the previous specification. You’ll notice that in this example we’re using facelets for the view technology:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<body></body>
</html>
Running the test now produces the following message:
java.lang.AssertionError: HtmlForm 'form' does not exist on page.
Ok, so now we need to place our components on the page. I’m going to add all three now to save space, but I would normally do this one at a time in quick TDD loops:
<body>
<h:form id="form">
<h:inputText id="username"/>
<h:commandButton id="login"/>
</h:form>
<h:outputText id="greeting"/>
</body>
Re-run our test and now we get the message:
java.lang.AssertionError: Expected: is "Hello, Rod!" got: null
So now, to actually implement some logical behavior to happen when the login button is pressed. First, let’s declare a managed bean in the faces-config.xml descriptor:
<managed-bean>
<managed-bean-name>LoginPage</managed-bean-name>
<managed-bean-class>com.steeplesoft.jsf.sample.LoginPage</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
And of course, actually create the bean.
public class LoginPage {
private String name;
private String greeting;
public String login() {
greeting = "Hello, " + name + "!";
return null;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getGreeting() {
return greeting;
}
}
Bind it to the actual components on the page:
<body>
<h:form id="form">
<h:inputText id="username" value="#{LoginPage.name}"/>
<h:commandButton id="login" action="#{LoginPage.login}"/>
</h:form>
<h:outputText id="greeting" value="#{LoginPage.greeting}"/>
</body>
Re-running our test shows passes, and running the application shows that our quick login page is now working correctly! We have been able to test drive the interaction of these user interface components in a simple and meaningful way.

We are planning on releasing 0.1, or first public release, sometime soon so keep an eye out here or at Jason’s site. Also, we are adding features in a test-driven manner meaning that we are using test scenarios like the simple one above to guide the functionality we’re building into FacesTester. Like to see some particular features in FacesTester? Just sketch out a test similar to the one above and send it to us. You’re input will help us out tremendously.
Your solution seems very slick and inline with the JSF design. We need a unit test solution that is more streamlined than JSFUnit.
Please add me to any mailing list for updates on this product.
Thanks for all your work!
David Nelson - March 30th, 2009 at 5:24 amHi David,
Thanks for your feedback. We’re definitely hoping that FacesTester becomes a strong alternative approach to JSFUnit and any feedback you can provide going forward would help us to do so. You can subscribe to our mailing lists at http://kenai.com/projects/facestester/lists. Once we do the first release I would expect some traffic to pick up on them. For the moment they’re silent.
Rod
rcoffin - March 30th, 2009 at 6:42 am