Sunday, December 14, 2008

First Code Example of Glimmer RSpec/SWTBot Testing

So, I mentioned in this >>blog post<< that Glimmer's now got Behavior-Driven Development support through RSpec and SWTBot.

In this post, I'll go over some of the technical aspects of how that works.

RSpec Cucumber is an engine that lets you map English statements (or any language actually) to executable code in order to validate software specifications written as scenarios with the code written to fulfill them. This is pretty much what Acceptance Tests in the XP process are.

Here is an RSpec Cucumber login.feature file that I wrote to test a Login (Glimmer) sample application:


Feature: Login feature
In order to keep user data secure
As a user
I would like to be authenticated before I can access my data

Scenario: Login
Given I fill in "User" for "Username"
And I fill in "Pass" for "Password"
When I "Login"
Then my status should be "Logged In"

Scenario: Logout
GivenScenario Login
When I "Logout"
Then my status should be "Logged Out"


The top 3 lines after the feature heading describe the user story being developed in the stakeholder language. Those lines are not executable.

The scenarios that follow however, which demonstrate the feature functionality, are written in the Given/When/Then format and executed to validate that the implementation satisfies the specification.

In order to execute these scenarios, you need to have code that can execute each step (statement on a line) in every scenario. Such code is arranged in *_steps.rb files. Here is how such code is written:


When /I fill in "(.*)" for "(.*)"/ do |text, label|
  @bot.text_with_label(label).text = text
end

When /I "(.*)"/ do |button|
  @bot.button(button).click
end

Then /my status should be "(.*)"/ do |text|
  @bot.label(text).should_not be_nil
end


The @bot object is actually an instance of the SWTBot class. This is an SWT driver that enables you to poke at an SWT desktop application by simulating a user filling in fields and initiating events like clicking a button.

Let's go through the steps one by one.

The following statement grabs a text box with the specified label, and sets its text property to whatever the text mentioned in the step is:


When /I fill in "(.*)" for "(.*)"/ do |text, label|
  @bot.text_with_label(label).text = text
end


This following statement on the other hand grabs a button based on the text that is displayed on it, and simulates a user click on it:


When /I "(.*)"/ do |button|
  @bot.button(button).click
end


Finally, this following statement looks for a label with the specified text and says that it should not be nil (null.) The should_not method is a method from RSpec that lets you write assertions using English-like statements as opposed to using the assert_equals method with two parameters:


Then /my status should be "(.*)"/ do |text|
  @bot.label(text).should_not be_nil
end


My code samples are still experimental and not ready to share yet. Once I have them in a good-enough state, I will commit them to the repository and blog about them in order to give people the opportunity to play with them.

1 comment:

Nicolas Marchildon said...

That's a good introduction to Cucumber, thanks!

I'm interested to try this out on an existing SWT application and I'm wondering how you can match a label text with the actual text field. Look at this simple example:

Label label = new Label(parent, SWT.NONE);
label.setText("User");
Text text = new Text(parent, SWT.NONE);

How do you do that?