Vaadin TestBench is an integration test tool, an extension to WebDriver. It simulates user interactions in real browser implementations. Thus, it is a great tool to really ensure things work as they should, from the browser level all the way to the database.
From low-level UI testing...
TestBench has been sometimes referred to as 'unit testing for the UI'. And in a way that's true, since in the most simple TB tests, we are only dealing with UI elements, element ids and XPath.
For nicer abstraction, the Page Object Pattern is a well-known solution to better keep your test cases readable and maintainable. We can call ‘services offered by the UI’ instead of just individual UI elements.
In large applications, however, even this might not be enough. There can be a mismatch between your tests and business requirements, because requirements work on a higher level of abstraction using different vocabulary. Luckily there is a way to climb even higher with Vaadin TestBench.
... to behavior-driven development.
Behavior-Driven Development (BDD) is an increasingly popular methodology to apply test driven development in a manner that aids project management as well, not just developers.
User stories and scenarios are written in such a way that they can be directly mapped to automated tests in the project. This forces requirements to be written in a clear manner that can be understood by all the stakeholders. And with proper tools and CI servers, it really helps everybody to follow the development and project status.
Vaadin TestBench can easily be configured to be a key part of your BDD software development process by using it together with other tools, such as JBehave.
JBehave is a popular behaviour-driven-development framework for Java. JBehave provides mapping from user stories, written in "customer readable" structured language, into actual test cases. With JBehave, you write tests using the Given-When-Then pattern, like this:
Scenario: Added contact shows in the search results Given the front page When the user clicks the add contact button And fills the contact details for the user Sven And searches for "Sven" Then the only row should contain the values Sven, Svensson, Vaadin Ltd.
These steps are matched into actual Java tests using annotations. So, for example, the "Given the front page" would be matched to a method with annotations like this:
@Given("the front page")
The method with this annotation would then interact with the application and perform the actions needed. And this is the way that we can wire JBehave together with TestBench.
Since TestBench tests are pure Java code and BDD steps can be run as JUnit tests, we can easily combine these in order to make JBehave drive TestBench. Start by extending the TestBenchTestCase provided by TestBench and use annotations from JBehave to manage the driver. In this example, @BeforeScenario and @AfterScenario are used to run code before each scenario:
@BeforeScenario public void beforeScenario() { setDriver(TestBench.createDriver(new FirefoxDriver())); getDriver().get("http://localhost:8080/?restartApplication"); } @AfterScenario public void afterScenario() { getDriver().quit(); }
Next we can just start annotating our test methods with @Given, @When and @Then, and calling driver methods directly.
Practical sample
To make it easier for you to get understanding of how all this works, we put together a small BDD scenario on top of the Vaadin addressbook sample. This shows a BDD project setup combining TestBench 4, JBehave and JUnit.
First, you need a user story. In our example, the user adds a new entry to the address book. High-level, English-like stories are easy to write. This is something that the business can do for you.
Like said, to keep the test code readable and maintainable, the different parts of the UI are abstracted using the Page Object pattern. Using page objects, it is easy to map the user stories to test cases using the JBehave annotations:
@When("searches for \"$name\"") public void searchesFor(String searchterm) throws Throwable { listPage.searchFor(searchterm); } @Then("the only row should contain these values:$expected") public void theOnlyRowShouldContainTheseValues(ExamplesTable expectedTable) throws Throwable { Listexpected = tableToBean(expectedTable, ContactRow.class); ContactRow expectedRow = expected.get(0); ContactRow resultRow = listPage.getOnlyResultRow(); assertEquals(expectedRow.getFirstname(), resultRow.getFirstname()); assertEquals(expectedRow.getLastname(), resultRow.getLastname()); assertEquals(expectedRow.getCompany(), resultRow.getCompany()); }
Take a look at the AddContact.story and AddContctSteps.java for a small example of how everything is wired to the actual UI.
Conclusion
While it might be overkill to use BDD for a small project, it is easy to see that it comes very handy in bigger development projects. Stories are much easier for non-developers (the business) to write, the BDD setup drives developers to use TDD practices, and keep the project communication consistent. Eventually all the stakeholders will have better awareness of the project status.