I accidentally agreed to give a talk later this month. The subject is IronRuby and it’s application in the .NET ecosystem. Seems simple enough. So, to jazz things up, I want to have a host of demo applications. This is about one.
A while back, I posted an article with an example of using IronRuby and the White framework. In it, I appear to have made a promise.
I’ll get to Cucumber. I’ll publish examples. I promise.
I’m going to talk a lot about Donny. You’ll meet Donny, but just be aware, he’s compiled in Debug, so he’s a bit shy. Donny is an app written to give me something to test. He does nothing of real import, he doesn’t even save his data to disk. As for why “Donny”, I still don’t know. I was in a mood yesterday when outlining my presentation and “Donny” stuck.
Cucumber – n, A functional testing framework for ruby. Cucumber uses Features and Step Definitions to drive an application via it’s full stack.
Cucumber does work with IronRuby, but by default it’s runner has some idiosyncrasies for which you’ll need to compensate. The cucumber.bat file lives, for me, in c:\IronRuby\lib\IronRuby\gems\1.8\bin. Another oddity is that it belives I have a color console. This is mostly true, but Win32Console doesn’t work for IronRuby, so you’ll need to use the --no-color option. For now. I have my features in a directory I’m calling “features” with an embedded step definitions directory. Once I finish the presentation, I’ll have the whole damn thing published and you can look at it then. Until then, here’s the command line I used; cucumber --no-colors features.
Feature – n, A tightly formatted Business Natural Language used to describe the preconditions, actions, and expected results in a business scenario. See also, Story.
I have two basic scenarios; Donny starts with no data, and Donny moves data from the task form to the task list.
Feature: New Task
In order to correctly bill my client
as an SEP employee
I want to add a task to the list
Scenario: Starting the app
Then all fields are blank
And the list contains 0 entries
Scenario: Add a new Task
Given I describe my task as Doing work on the Donny app
And I'm working on project Academy
And the day is Monday
And I worked from 10 to 10:30
When I press the button
Then all fields are blank
And the list contains 1 entry
And the last entry is Monday 10-10:30 Academy Doing work on the Donny app
Step Definition – n, a ruby script used to match lines in the Feature BNL to actual executable code. They can be reused across features.
For each Given, When, or Then I have to have a matching step. These are essentially ruby functions that use a helper to encapsulate my usage of the White library. Here is donny_steps.rb
require 'spec/expectations' require File.dirname(__FILE__) + "/../../donny_helper.rb" Before do @app = Application.launch "Donny/bin/Debug/donny.exe" @win = @app.get_window "Window1" @tf = TaskForm.new(@app, @win) @tl = TaskList.new(@app, @win) end After do @win.close end Given /I describe my task as (.*)/ do |description| @tf.description = description end Given "I'm working on project $proj" do |proj| @tf.project = proj end Given "the day is $day" do |day| @tf.day = day end Given /I worked from (.*) to (.*)/ do |start_time, end_time| @tf.start_time = start_time @tf.end_time = end_time end When "I press the button" do @tf.commit end Then "all fields are blank" do @tf.description.should be_empty @tf.project.should be_empty @tf.day.should be_empty @tf.start_time.should be_empty @tf.end_time.should be_empty end Then /the list contains (.*) entr(?:y|ies)/ do |n| @tl.task_count.should == n.to_i end Then /the last entry is (.*)/ do |result| @tl.tasks.last.text.should == result end
Um, you’re missing a piece. The part that uses White. Remember the screens? This time, I didn’t call them screens, and I don’t have a full window proxy, but I still have two helper objects. Now, with some metaprogramming, I could cut down the code size by defining an attribute and describing the type and automation ID of it’s associated control, but I’m lazy. Maybe for the presentation, but I’m not making any promises.
white_loc = (File.dirname(__FILE__) + "/White_Bin_0.18/")
puts white_loc
$LOAD_PATH << white_loc
require "White.Core.dll"
Application = Core::Application
ComboBox = Core::UIItems::ListBoxItems::ComboBox
ListBox = Core::UIItems::ListBoxItems::ListBox
Window = Core::UIItems::WindowItems::Window
include Core::UIItems
class Window
def get_button(*args)
self.method(:get).of(Button).call(*args)
end
def get_textbox(*args)
self.method(:get).of(TextBox).call(*args)
end
def get_combobox(*args)
self.method(:get).of(ComboBox).call(*args)
end
def get_listbox(*args)
self.method(:get).of(ListBox).call(*args)
end
end
class TaskList
def initialize(app, win)
@app = app
@win = win
end
def tasks
@win.get_listbox('tasklist').items.to_a
end
def task_count
tasks.size
end
end
class TaskForm
def initialize(app, win)
@app = app
@win = win
end
def description
get_tb 'task'
end
def description=(text)
set_tb 'task', text
end
def project
@win.get_combobox('project').selected_item_text
end
def project=(proj)
@win.get_combobox('project').select proj
end
def day
get_tb 'dayofweek'
end
def day=(day)
set_tb 'dayofweek', day
end
def end_time
get_tb 'endtime'
end
def end_time=(et)
set_tb 'endtime', et
end
def start_time
get_tb 'starttime'
end
def start_time=(st)
set_tb('starttime', st)
end
def commit
@win.get_button('commit').click
end
private
def set_tb(auto_id, value)
@win.get_textbox(auto_id).set_value value
end
def get_tb(auto_id)
@win.get_textbox(auto_id).text
end
end
And some for some context, Meet Donny!
And, after I enter a task, Donny looks like this.
That's really all there is to using Cucumber with IronRuby. Have fun!