Behavior-Driving Your Apache Wicket Application

Making the Most of WebDriver and JDave-Wicket

This material is meant for supplementing the "Behavior-Driving Your Apache Wicket Application" training session on Tuesday, 24 March at the ApacheCon EU 2009 conference in Amsterdam. If you are interested in the theme but cannot make it to the training, you might still find this site useful.

Getting Started

If you are coming to the training, please do at least the following to get started:

0) Install

  • Java (at least 1.6)
  • Maven 2 (at least 2.0.9)
  • Firefox 2 (Firefox 3 might work as well, Firefox 3.1 beta might work better than 3.0.x)
  • Subversion (at least 1.5)
  • The IDE you use for Java development, preferably Eclipse or IntelliJ IDEA (we don't know Netbeans!)

1) Get the latest project code from

https://github.com/jdave/kansanpankki

(for example

git clone git://github.com/jdave/kansanpankki

)

2) build the project with Maven to get the necessary dependencies and their source code

cd kansanpankki
  mvn eclipse:eclipse
  mvn clean install

3) If you have a problem with the build, please try to resolve it before the training.

4) Checkout the different branches to get the base situations for different exercices.

(for example

git checkout -b 00_initial_situation origin/00_initial_situation

)

You can start the software by running the main method from a class called Jetty. The WebDriver specs use a different port, so they shouldn't conflict with that. If you use JavaRebel and want to run the WebDriver specs faster, you can start WebDriverJettyStarter with JavaRebel and then the WebDriver specs should use it.

The Firefox binary used by WebDriver can be chosen by supplying a value for the webdriver.firefox.bin system property, for example -Dwebdriver.firefox.bin=firefox-2. At least on MacOS, the property value should not contain spaces.

Behavior-Driven Development with JDave

Behavior-Driven Development (BDD) is a way of programming that developed out of Test-Driven Development (TDD). Technically the two are very similar, and many even consider BDD being "TDD done right". This is reflected in the fact that the paper "A New Look at Test-Driven Development" by Dave Astels in 2005 can be seen to mark the birth of BDD.

With TDD, it's possible to write tests in a very whitebox testing way that exposes the internals of the tested classes. This is considered bad practice, and the tests should instead reflect the expected behavior of the objects in certain states and interacting with other objects in certain ways.

Empty account
- has balance of 0
- cannot move money to another account
- can receive money from another account

Account with money
- can move money to another account

=>

public class AccountTest {
    @Test public void emptyAccountHasBalanceOf0 { ... }
    @Test public void emptyAccountCannotMoveMoneyToAnotherAccount { ... }
    @Test public void emptyAccountCanReceiveMoneyFromAnotherAccount { ... }
    @Test public void accountWithMoneyCanMoveMoneyToAnotherAccount { ... }
}

=>

public class AccountSpec extends Specification<Account> {
    public class EmptyAccount {
        public Account create() { return new Account(0); }
        public void hasBalanceOf0 { ... }
        public void cannotMoveMoneyToAnotherAccount { ... }
        public void canReceiveMoneyFromAnotherAccount { ... }
    }

    public class AccountWithMoney {
        public Account create() { return new Account(9500); }
        public void canMoveMoneyToAnotherAccount { ... }
    }
}

The BDD "tests" tend to be called specifications (or specs). On one hand, plain text scenarios (in BDD tools such as RSpec or JBehave) or names (in BDD tools such as JDave) intend to contain textual specification. On other hand, the code executed in the "test methods" tries to convey the essential examples of the usage of the object that demonstrate that the specification is fulfilled. So BDD can also be seen as specifying by examples. (See Marick for a discussion between examples and specifications.)

JDave is a Java BDD framework that has been around for a couple of years. Its central ideas are the following.

1. There is normally one specification class, extending jdave.Specification, per specified class.

2. The specification subclass contains inner classes called contexts. There is a separate context for each interesting state that the specified (tested) object may have.

3. Each public method of a context class is a behavior, whose name indicates an expected behavior of the context, and whose implementation enforces the behavior with relevant examples. Remember that a context is the object under test in a certain state, so the behaviors of a context reflect the expected behavior of the object in that state.

4. JDave provides a JUnit 4 runner, so that JDave specs can be executed with any tool that can execute JUnit tests (such as Maven, Eclipse, IntelliJ IDEA or Buildr).

JDave provides a couple of modules that facilitate writing specs for some specific technologies. In this training, we'll cover jdave-wicket for writing unit test style specifications for Wicket components, and jdave-wicket-webdriver for writing black box functional test style tests for (Ajax) Wicket applications, employing the WebDriver functional testing tool for commanding a Firefox browser to use the application.

WebDriver

WebDriver is a tool for automating functional tests of web applications. It is similar to Selenium and seems like it will be incorporated into Selenium at some point.

With WebDriver, the developer writes Java code to command the browser and inspect the produced HTML. WebDriver takes care of most of the details. In the case of Firefox, it installs a new profile and then the functionality it needs as a Firefox plugin.

The added value that jdave-wicket-webdriver provides is

1. A simple object-oriented model for writing the WebDriver specifications

2. An integrated mechanism for waiting for Wicket Ajax requests to complete

3. Some common mechanisms for initialising the Firefox driver of WebDriver and other plumbing that must be done by any specification

With the programming model of jdave-wicket-webdriver, it is possible to encapsulate the WebDriver-specific details in reusable objects called elements. By naming the element classes and their methods well, they can be grown to resemble a domain-specific language (DSL) about the user interface of the application under test. This way, the specification code using the elements becomes very expressive.

ItemsListElement itemsList = searchElement.searchFor("mp3 player");
specify(itemsList.countItems(), does.equal(19));
specify(itemsList.nameOfElement(1), is("Pop blaster"));
specify(itemsList.nameOfElement(2), is("Frank's TurboPlayer 2000"));

The jdave-wicket-webdriver element concept is similar to the [page objects of WebDriver|see http://code.google.com/p/webdriver/wiki/PageObjects].

In our experience, WebDriver has worked best when

  • using snapshots
  • using FireFox 2
  • using Linux (or Windows)

Outline of the Session Schedule

This session is a full-day training which means that it consists of two three-hour sessions with lunch in between.

Morning 10.00-13.00
  • general presentation of BDD / JDave and the demo application 10-10.15
  • checking the dev environments of people 10.15-10.30
  • a demo on JDave 10.30-10.45
  • 1st exercice: an easy JDave task 10.45-11.15
    • some domain logic driving on JDave
    • Account.java
  • feedback on exercise 11.15-11.30
  • break 11.30-11.45
  • 2nd exercise: a more difficult jdave-wicket task 11.45-12.45
    • implementing new Wicket features
    • seeing the current balance of each account in the list
    • making a transaction and seeing its effects on account balances
  • feedback on exercise 12.45-13.00
Afternoon 14.30 – 17.30
  • general presentation of WebDriver and jdave-wicket-webdriver (Elements) 14.30-14.45
  • a demo on jdave-wicket-webdriver 14.45-15.00
  • 3rd exercise: an easy WebDriver task 15.00-15.30
    • testing the transfer between two own accounts with WebDriver
  • feedback on exercise 15.30-15.45
  • break 15.45-16.00
  • 4th exercice: a more difficult WebDriver task 16.00-17.15
    • implementing the listing of transactions of an account, driving with WebDriver
  • feedback 17.15-17.30

Get in Touch

If you have any questions or comments, don't hesitate to contact us at firstname dot lastname at ri dot fi!

- Markus Hjort, Timo Rantalaiho, Marko Sibakov