Coming Up for Air

Announcing FacesTester

Tuesday, March 03, 2009 |

One of the issues that has always troubled me with regard to writing JSF applications (or any web application, really) is how hard it is to test them. Some time ago, while discussing various Java web frameworks, I stumbled across a class called WicketTester, which is part of the Wicket project. Using this class, as best as I can tell, Wicket authors can easily test their applications very quickly. Having taken the advice of Dale Hanchey, and old college professor of mine, "Never be too proud to steal a good idea," FacesTester was born.

Unit testing a JSF application can be tricky, and there are a lot of different opinions and techniques for doing so. Stan Silvert from JBoss, for example, just released a GA version of JSFUnit, an in-container end-to-end testing framework for JSF. Dan Allen, also of JBoss but working on the Seam project, recently discussed SeamTest in this wiki entry. What bothers me about both of those solutions, though, is the need for a container. What I’d like to be able to do is write a plain, simple JUnit test to exercise my managed beans, converters, etc. without the start-up penalty of starting a container (even if it’s embedded) or deploying a .war to a container. That’s where FacesTester fits in. Though in a very early stage, FacesTester is intended to allow a JSF application developer to inspect the component tree, validate the logic and/or output of managed bean methods, etc. with a very simple and light weight API.

As exciting as that may sound (I don’t know about you, but in my head, it’s REALLY exciting : ), don’t get carried away yet. I started this project in a very low-key fashion several weeks ago, and poked at it in my scant free time. Last week, though, I got a call from my good friend Rod Coffin, who had some unrelated JSF questions. In the course of the conversation, testing came up, and I mentioned this pet project of mine. Rod, a huge proponent of testing in general, immediately bit on the idea and volunteered to help. Since that conversation, we have gotten the project to the state where we can instantiate the FacesServlet and request a page from our application. We can then request a specific component and perform various tests on it. Since we’re leveraging the real, live FacesServlet, we get all the JSF goodness, including EL support, for free. Here’s an example (contrived, dumb, simple, etc) test:

1
2
3
4
5
6
7
<h:form id="form">
    <h:outputLabel id="stateLabel" value="State"></h:outputText>
    <h:outputText id="elTest" value="#{4+5}"></h:outputText>
    <h:outputText id="renderedTest" rendered="false"
        value="RenderedTest">
    </h:outputText>
</h:form>

Given that page definition, we can then test it like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class WhenNavigatingToPage {
    private FacesTester tester;
    @Before
    public void setUp() throws Exception {
        tester = new FacesTester();
    }
    @Test
    public void shouldBeAbleToAssertValueOfComponents() throws Exception {
        assertThat(tester.requestPage("/address.xhtml").getComponentWithId("form:stateLabel")
            .getValueAsString(), is("State"));
    }
    @Test(expected = AssertionError.class)
    public void shouldBeAbleToAssertValueOfNoExistentComponents() {
        tester.requestPage("/address.xhtml").getComponentWithId("unknown");
    }
    @Test
    public void shouldBeAbleToEvaluateEl() throws Exception {
        assertThat(tester.requestPage("/address.xhtml"), is ("9"));
    }
    @Test
    public void shouldBeAbleToTestRendered() throws Exception {
        FacesComponent component = tester.requestPage("/address.xhtml")
            .getComponentWithId("form:renderedTest");
        assertThat(component.getValueAsString(),is ("RenderedTest"));
        assertEquals(component.isRendered(), false);
    }
}

As cool as that is, that’s about the extent of the API at the moment, but Rod and I are very excited about what we might be able to offer with this. The next big step for me is to get form submission working, and Rod is going to look at writing more tests and letting those drive the capabilities of FacesTester, as well writing some unit tests around bootstrapping the environment from different web.xml files. There’s a lot to be done still, so if you’re interested, head over to the project home page on kenai.com and join the fun!

Search

    Quotes

    Sample quote

    Quote source

    About

    My name is Jason Lee. I am a software developer living in the middle of Oklahoma. I’ve been a professional developer since 1997, using a variety of languages, including Java, Javascript, PHP, Python, Delphi, and even a bit of C#. I currently work for Red Hat on the WildFly/EAP team, where, among other things, I maintain integrations for some MicroProfile specs, OpenTelemetry, Micrometer, Jakarta Faces, and Bean Validation. (Full resume here. LinkedIn profile)

    I am the president of the Oklahoma City JUG, and an occasional speaker at the JUG and a variety of technical conferences.

    On the personal side, I’m active in my church, and enjoy bass guitar, running, fishing, and a variety of martial arts. I’m also married to a beautiful woman, and have two boys, who, thankfully, look like their mother.

    My Links

    Publications