As we announced earlier, we are undergoing several changes in our approach to how RichFaces is tested. We already have an extensive functional test suite authored by a top-notch RichFaces QE team, but this suite doesn’t allow us to react quickly on regressions introduced and so we usually find some of them during release testing.

We came to the conclusion that we are doing testing too late after a commit and that the tests we have are too far from a real environment – they are not real enough.

The Integration Environment Complexity

The problem which we face is given by the complexity of the client-server nature of web frameworks like JSF.

In RichFaces, we build on top of client-side libraries (jQuery, jQuery UI, etc.) that communicate through the JSF client-side library with the JSF backend to an application server.

The testing of client-side interactions is then so complex that it is often not covered by tests at all.

But while one is avoiding testing of client-side interaction, he might easily underestimate its importance.

Client-side code is very fragile due to diversity of browser implementations – its testing is unavoidable in every serious project.

Standard approaches

The code we write in RichFaces component library can be easily unit tested and so we test regularly units both on the client-side and on the server-side.

But the real working units we need to test are in fact JSF components. They are composed from client-side code (Javascript and CSS), XML templates, Java code and XML configuration. There are currently only limited options to test them in unit-testing fashion. None of them is really effective.

This is the usual story when it comes to integration testing.

Mocking

One might think that this is a case for testing by mocking. So did we.

After years of development, we ended up with many mocks and we got nothing in return other than hard work for a compiler and huge amount of code to maintain. These mocked tests we had were not really guarding us against code modifications and refactoring. Yeah, the mock-based tests are pretty fast, but they don’t guard us from bugs.

You might know that situation – why you should write a test when you don’t believe it will help you to verify correctness and enable change?

Using mocks for a component or integration testing is not a way to success.

Arquillian for the Rescue

Fortunately there is one team which lives with the idea “Stop Mocking at All” in mind, and focuses on getting testing real again.

Effortless Test Harness

Arquillian integrates with (almost) every application container out there in a unified manner, so it’s very easy to set your application for a cross-container testing.

Easy Packaging

For a packaging of application pieces, you can leverage the ShrinkWrap API to easily achieve either packaging of micro-deployments or the whole application (using ShrinWrap Resolvers). Additionally, you can use a fluent API for describing the deployment configuration (ShrinkWrap Descriptors).

Get Me a Real Browser

From the perspective of web UI testing it is important that Arquillian allows the control of real browsers using a Drone extension. Drone brings a browser to the test and exposes it using the widely-adopted WebDriver API

@Drone WebDriver driver;

No matter which browser you use, you will write the same test just once and you will be empowered to run it on (almost) every browser out there in an unified manner.

In this way, you can run your tests everywhere:

  • on various versions of mainstream desktop browsers
  • on various mobile devices (emulated or real)
  • on mocked browsers
  • remotely on virtualized browser grids (on-demand)
  • remotely using a cloud browser provider
Note: WebDriver is the Selenium 2 API, which is undergoing the process of W3C standardation.

Arquillian Saves the Day

With Arquillian, you can let the browser of your choice talk to the application server of your choice.

But you can do much more and test more effectively if you will look at additional Arquillian’s extensions:

Gray-Box Testing

Warp your test from the Client to the Server.

In server-side web frameworks, you typically do complex interactions which involves a portion of client-side code and a portion of server-side state manipulation. But how to test more complex interactions? What happens when we trigger client-side code (e.g. hit a button)? What is the reaction on the server-side (e.g. are CDI events raised)?

That’s exactly where a Arquillian Warp extension comes in – it allows you to write tests as a combination of client-side activities and inspect what is happening in the server as simply as

Warp
    .initiate(Activity)
    .inspect(Inspection);

It allows you to perform anything you can imagine on the client-side and once your client makes a HTTP request to the server, you can inspect what happens on the server-side.

During a server inspection, you can inject, test and assert state injected of the application in the same way as you would do in Arquillian’s in-container test.

@Inject MyBean myBean;

@AfterPhase(INVOKE_APPLICATION)
public void verifyThatBeanWasInvoked() {
	myBean.wasIInvoked()?
}

In the words of JSF, you can manipulate the JSF components on the page and you can inspect what happens to the application state throughout the JSF lifecycle, looking at the state of your beans or what messages were produced as the response to the user’s action and much more.

Warp is outstanding servant when it comes to testing the real client-server interaction.

Note: Warp is officially a successor of JSFUnit project.

Testing AJAX-heavy applications

You could be all setup now, but you will quickly come to a conclusion that WebDriver itself isn’t strong enough to deal with highly-interactive AJAX-based applications (as applications built with RichFaces are). This is where Graphene comes in.

Arquillian Graphene allows you to precisely and concisely describe what interactions happen in the browser so the test will execute deterministically:

addButton.click();
waitGui().until().element(newRecord).is().present();

assertEquals(..., newRecord.getText());

Ironically, it is even simpler to wait for updates from a server, since Graphene allows you to guard a communication between client and server – it blocks the test execution until the communication ends:

searchInput.sendKeys("Java Testing Platform");
guardXhr(searchButton).click();
assertEquals("Arquillian", searchResults.get(0).getText());

Graphene is an awesome tool for dealing with AJAX-heavy pages.

Page Abstractions

Using the WebDriver API, you need to manipulate the page with the low-level web APIs: HTML, DOM, CSS, JavaScript. The tests can quickly become hard to read and maintain.

That’s why we have adopted a Page Objects pattern which enables you to abstract the complexity to reusable pieces.

In Graphene, you can define so called Page Fragments, which will allow you to abstract small pieces of pages which are used repeatedly and reuse them through your projects.

In the world of JSF, those pieces can be JSF components:

@FindBy(id = "form:birthDate")
RichfacesCalendar birthDate;

@Test
public void test() {
    birthDate.setDate(xyz);
}

The same way JSF abstracts UI components, you can abstract your testing logic.

Conclusion

Arquillian opens you to pretty new testing experiences – it makes writing tests as easy as unit testing, while keeping the tests real, concise and fun to write.

Next Time

This is the first part of blog series which will allow you to look under the hood of how we designed tests for RichFaces based applications (and how we actually test RichFaces itself).

In the next parts, I will focus on how to:

That’s it for now! See you next time…


blog comments powered by Disqus