
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!
