Thursday, June 17, 2010

Three time-saving tips you didn't know in testing Wicket pages

If you use the excellent Wicket framework to development web applications, with the Wicket Page Test library, the following tips will greatly reduce your turn-around time during development:

Tip 1: Install mock objects into your page so that it won't hit the database during the unit test


For example, the page below usually will use a Spring bean to load a Product object from the database:

public class Page1 extends WebPage {
@SpringBean
private MyService service;

public Page1(String productId) {
Product p = service.loadProduct(productId);
...
}
}

In the unit test, you can install a mock object to replace the service like:

@Test
public class Page1Test {
private Product p1;

public void test1() {
p1 = new Product(...); //hard code Product
MockableSpringBeanInjector.mockBean("service", new MyService() {
public Product loadProduct(String productId) {
return productId.equals("p1") ? p1 : null;
}
});
DefaultSelenium selenium = ...;
selenium.open(...); //open the page
assert ...; //inspect the HTML elements
}
}

Tip 2: Test real AJAX effect and wait for AJAX completion easily


You can, say, click an AJAX link or AJAX button and wait for the completion easily like:

@Test
public class Page1Test {
public void test1() {
Selenium selenium = ...;
WicketSelenium ws = new WicketSelenium(selenium);
...
selenium.click("link=Buy"); //click an AJAX link
ws.waitUntilAjaxDone(); //wait until page is refreshed
assert ...; //inspect the HTML elements
}
}

Tip 3: Locate the HTML element generated by a given Wicket component easily


For example, to click the link generated by a Wicket Link component whose ID is "productDetails", just the special wicket locator:

@Test
public class Page1Test {
public void test1() {
Selenium selenium = ...;
...
//locate the link whose Wicket ID is productDetails
selenium.click("wicket=//productDetails");
selenium.waitForPageToLoad("3000");
assert ...; //inspect the HTML elements
}
}

You can even look further for a descendant component using something like //product//order (the order button for the product) or even use an index (if you have a loop) like //product[3]//order (the order button for the 3rd product).


To apply these tips, get the open source Wicket Page Test library. There is a step-by-step tutorial there.


Disclosure: I am the creator of Wicket Page Test.