<< Part 2 – A quick look at IronRuby
Gambling with Cucumbers
In
part 2 we demonstrated how we can mix .NET and Ruby though IronRuby. The question is, why would you want to do that? It is probably easier to stick with one language for most projects. Why combine them?
The problem with BDD in .NET
One area where Ruby currently has a clear advantage over.NET is in the realms of Behavioral Driven Development (
BDD).
You can write
Unit Tests and
Integration Tests in .NET just fine, but what about when you want to make tests based on actual user stories? Specifications written as word documents and UML diagrams have a tendency to evolve separately to the actual product. If you could replace the specifications with human readable tests specifications it could easier to keep the product’s functional requirements in sync with the actual implementation.
The problem with this is that not everyone involved with the product is necessarily going to be a programmer. For example, this
NUnit test a
poker hand that should make up “One Pair”:
[TestFixture]
public class DemoTests
{
Hand _hand;
[SetUp]
public void SetUp()
{
_hand = new Hand();
}
[Test]
public void Should_show_one_pair_for_3c_3s_Jc_9d_As()
{
_hand.AddCard("3 clubs");
_hand.AddCard("3 spades");
_hand.AddCard("J clubs");
_hand.AddCard("9 diamonds");
_hand.AddCard("A spades");
Assert.AreEqual("One Pair" , _hand.EvalScore());
}
.
.
.
}
This makes plenty of sense to developers, not so much to business professionals. And this is a relatively readable test, what if theres mocking and other distractions?
Now compare that with the popular Ruby BDD framework,
RSpec:
# hand_spec.rb
require 'IronPoker'
describe Hand do
it "show a score of 'One Pair' if player has " +
"3 Clubs, 3 Spades, J Clubs, 9 Diamonds and A Spades" do
20.times { bowling.hit(0) }
bowling.score.should == 0
hand = IronPoker::Hand.new
hand.add_card "3 Clubs"
hand.add_card "3 Spades"
hand.add_card "J Clubs"
hand.add_card "9 Diamonds"
hand.add_card "A Spades"
score = hand.eval_score
score.should = "One Pair"
end
end
Much cleaner!
And you can also use command line tools to generate reports:
$ spec hand_spec.rb --format specdoc
Hand
- show a score of 'One Pair' if player has 3 Clubs, 3 Spades, J Clubs, 9 Diamonds and
A Spades
Finished in 0.007534 seconds
There have been attempts at creating similar frameworks for .NET, but there are syntactical constraints that make it difficult to keep the readability. For example, my favorite .NET BDD framework is
MSpec (also known as Machine Spec). Here is what an MSpec spec looks like:
// machine.spec (mspec) sample
using IronPoker;
[Description]
public class Player_showing_their_hand
{
static Hand _hand;
Context before_each = () =>
{
_hand = new _Hand();
};
When 3_clubs_and_3_spades_and_J_clubs_and_9_clubs_and_A_Spades_are_dealt = () =>
{
_hand.AddCard("3 clubs");
_hand.AddCard("3 spades");
_hand.AddCard("J clubs");
_hand.AddCard("9 diamonds");
_hand.AddCard("A spades");
_result = _hand.EvalScore();
};
It should_show_a_score_of_One_Pair = () =>
{
_result.ShouldEqual("One Pair");
};
}
Sure it looks a bit like RSpec, but notice how the When…It… descriptions have to be separated by underscores, and the use of the unsightly “= () =>” lambda syntax at the end of each clause? There are other BDD frameworks, but they all have to make compromises somwhere. (In fairness to MSpec, it does at least have a tool which generates very nice html RSpec style reports though!).
Cucumber, Finally!
As nice as RSpec is, we can do even better when it comes to turning user stories into tests. Cucumber is an RSpec extension that lets you write tests like this:
Feature: Player shows their hand
In order to finish the round
The player
Needs to show their hand
Scenario Outline: Play is dealt a card
Given I have a <card_1> in my hand
And I have a <card_2> in my hand
And I have a <card_3> in my hand
And I have a <card_4> in my hand
And I have a <card_5> in my hand
When I am dealt a card
Then the result should be <output> on the screen
Examples:
| card_1 | card_2 | card_3 | card_4 | card_5 | output |
| 3 Clubs | 3 Spades | J Clubs | 9 Diamonds | 3 Spades | One Pair |
Makes sense, right? The first section, “Feature” describes in plain English the story and use case. The scenario is described in the what appers to be plain English, but actual confirms to a “Given… When… Then” structure. And final the table of examples directly correlates to the parts of the Scenario bracketed names (card_1, card_2 etc).
Because part Cucumber is part of RSpec this means it also implemented in Ruby. Sounds like a job for IronRuby!
Lets try it out!
IronPoker tutorial
For this demonstration we are going to try out Cucumber on an incomplete .NET application application I’m calling “IronPoker”. I got as far as writing the code to analyse poker hands written
TDD style using NUnit. Lets switch and let Cucumber have a go!
The IronPoker code is in
github:
You can either checkout the code using
Git, or click on the
Download button to retrieve the it in the form of a .zip file. The solution file is in Visual Studio 2008 format, but don’t worry if you don’t have it, we are going to work with Cucumber from the windows command interpreter.
Incidentally if you build and running IronPoker from Visual Studio there is not much to see there. The executable is a stub:
The bulk of code currently written is all in the ‘IronRuby’ class library. Its just logic to calculate scores. Feel free to poke around in ‘IronPoker.Tests’ if you want to get a feel for it does. But we’re here for the cucumber, right? Open up a command prompt, navigate to this folder:
IronPoker\src\IronPoker.Cucumber
and we’ll run the cucumber test found in the subfolder:
.\Features\PlayHand.Feature
by running:
icucumber.bat Features
Note: if you start seeing “[36” spread liberally through the output, this means that the console colors do not work in your version of ruby. I have the same problem. See the Cucumber installation comment in Step 1 of this guide for details on how to turn it off.
Anyway, here are the results (in boring monochrome):
Cucumber parsed the “feature” file, but didn’t find an implementation. Generously, it hass given us some code to get started with!
We have an implementation file already, but it is empty. It is here:
.\Features\steps\ironpoker_steps.rb
Copy and paste the implementation so far. (Copy and paste is available from the top left menu of the command window).
As you may have gathered, this is ruby code. Next we need to figure out how to drive our IronPoker .NET code from IronRuby. This is where the “IIRB” tool comes in handy! (Reminder, its accessed by running “iirb.bat” from the windows command interpreter).
First off we need access to IronPoker.dll, which can be built from the “IronPoker” class library. You don’t need build it though because a copy of it is already in the IronRuby.cucumber folder, just to keep things simple! We can load it with:
require 'IronPoker'
Next we need to test the IronPoker.Hand class, as found in IronRuby\Hand.cs. So lets make an instance of it:
hand = IronPoker::Hand.new
Which of course is the same as saying “
var hand = new IronPoker.Hand()” in C#.
Remember that NUnit sample we looked at earlier? We’re looking to do the same thing with Cucumber. So we need access to
AddCard() and
EvalScore() methods to run our tests. We can inspect which methods are available to us by running method called
methods. Every ruby object has this:
There they are! Only because the function names have been rubyized, they have become
add_card and
eval_score.
Let try playing a hand:
Yep, Ace, 2, 3 ,4 and 5 of spades is indeed a ‘Straight Flush’.
Now we just have to do something similar for Cucumber. Time to go back to implementing ironpoker_steps.rb. First off stick this at the top of the code before the Given statements:
require 'IronPoker' # IronPoker.dll
Before do
@hand = IronPoker::Hand.new
end
The Before clause is the equivalent of the “SetUp” method in typical unit testing frameworks. In other words, It is the function that gets called before each test. In this case the “hand” object is a member instance rather than a local instance so it has the extra @ at the front.
Next we need to to call
add_card for each of the 5 given statements. We can actually reduce it down to one statement though thanks to regular expression:
Given /^I have a (.*) in my hand$/ do |c|
# c = (.*)
@hand.add_card c
end
In ruby, regular expressions are encapsulated between forward slashes. So we just have one given statement with a regular expression wildcard (.*) on the part that changes, the card descriptions. The body of the Given block assign the text from the wildcard to the variable “c” and uses it as the argument for “@hand.add_card”.
This will be the When block:
When /I am dealt a card/ do
@result = @hand.eval_score
end
Which is saying that when the player receives a card it will be evaluated and stored in @result. In the case of the test, this applies for when the player has all 5 cards.
Finally in the Then block we evaluate whether or not the conditions of the test are met:
Then /the result should be (.*) on the screen/ do |score|
@result.should == score
end
So @result is compared to the wildcard (which was assigned to “score”). So its roughly the same as an Assert in a unit testing framework.
Put it all together and we have:
Save that and we can run our cucumber test again:
The test completed! Only problem is the result was “Three of a kind” instead of “One pair”. It actually is a Three of a kind, so the test is wrong!
Easily fixed, change one of the 3s to an A and it should pass.
Also why not add some more examples to the examples talbe in ‘PlayHand.Feature’? Try changing the examples section to this:
Examples:
| card_1 | card_2 | card_3 | card_4 | card_5 | output |
| 3 Clubs | 3 Spades | J Clubs | 9 Diamonds | A Spades | One Pair |
| 9 Diamonds | J Diamonds | Q Diamonds | K Diamonds | A Diamonds | Royal Flush |
| 8 Spades | J Diamonds | 8 Diamonds | K Spades | 8 Hearts | Three of a Kind |
| 8 Spades | J Spades | 8 Spades | K Spades | 8 Spades | Flush |
| 2 Spades | 2 Diamonds | 8 Diamonds | 2 Clubs | 2 Hearts | Four of a Kind |
| A Hearts | 2 Diamonds | 3 Spades | 4 Clubs | 5 Spades | Straight |
| 9 Diamonds | A Hearts | 9 Clubs | A Spades | A Hearts | Full House |
| 4 Hearts | 5 Hearts | 6 Hearts | 7 Hearts | 8 Hearts | Straight Flush |
| A Spades | 4 Diamonds | 5 Diamonds | 9 Diamonds | 8 Diamonds | High Card |
| A Spades | 4 Diamonds | A Diamonds | 4 Clubs | 8 Clubs | Two Pair |
Giving us:
And that’s a wrap! (I would say "cucumber wrap" but there are Laws...)
Reference Sources
These are some of the sites which I used to research the tutorial, and a few more that you may find helpful:
Installation
Ruby -
http://www.ruby-lang.org/
IronRuby -
http://ironruby.net
Cucumber -
http://wiki.github.com/aslakhellesoy/cucumber/ironruby-and-net
IIRB/DLR
http://msdn.microsoft.com/en-us/magazine/dd434651.aspx
http://silverlight.net/content/samples/sl2/dlrconsole/index.html
TDD/BDD
NUnit -
http://www.nunit.org/index.php
Machine Spec -
http://codebetter.com/blogs/aaron.jensen/archive/2008/05/08/introducing-machine-specifications-or-mspec-for-short.aspx
RSpec -
http://rspec.info/
Cucumber -
http://cukes.info/
<< Part 1 - Installing IronRuby and Cucumber
A quick look at IronRuby
Background
IronRuby is an implementation of Ruby which runs on .NETs Dynamic Language Runtime platform (the DLR). Languages hosted on the DLR are interpreted at runtime, rather than compiled then executed (like C# applications).
One benefit is that code can be invoked on the fly from a command line shell. This is handy when debugging or figuring out how to do something. Other popular DLR hosted languages include
IronPython and
Silverlight.
Messing around with Interactive IronRuby Shell (IIRB)
In standard ruby the interactive shell is invoked by running “IRB”. With IronRuby we prefix it with an extra “I", giving us “IIRB”.
Let's try that. From a windows command prompt type
iirb.bat<enter>:
This looks exactly like the standard Ruby IRB, but the unfortunate delay on loading is a giveaway. Hopefully that delay will reduce as the framework matures!
First off, lets confirm that it is a Ruby interpreter. Try making it interpret some basic ruby expressions:
"live racecar !"
"live racecar !".reverse
"live racecar !".reverse * 5
("live racecar !".reverse * 5).split(" racecar ")
("live racecar !".reverse * 5).split(" racecar ").map {|x| result = "We" + x}
These are the result I got:
Yep, it looks just like conventional Ruby so far! Of course there is a lot more to Ruby, but we’re not going to cover it here. Try these resources instead:
So, how about something you can’t do in standard Ruby? How about we use IIRB to show a .NET
MessageBox?
Showing .NET MessageBoxes
First we need access to the .NET libraries. For accessing a message box in .NET app we would need to add a reference to a library like ‘
PresentationFramework.dll’.
In IronRuby we do this through the
require keyword. Excute this from the IIRB:
require 'PresentationFramework'
Now we can have access to the message box. Try this next:
System::Windows::MessageBox.Show("Mein fruhstuck ist sehr langweilig!",
"IronRuby Demo")
You should now see this:
This is almost the same as using the MessageBox object from C#, except that we are using “::” instead of “.” to separate namespaces and there is no semicolon at the end.
Personally I don’t want to keep referring to MessageBox namespace every single time I use it. Let's create another
MessageBox object with a shorter name:
MessageBox = System::Windows::MessageBox
MessageBox.show 'Mein fruhstuck ist noch immer sehr langweilig!',
'IronRuby Demo'
You may notice that I also switched over to using the Ruby style lowercase version of “Show()” method and that I dropped the parenthesis. I also switched to apostrophes instead of quotes. This is just another way of doing the same thing in Rubyland.
So... we can now can show a message box. Big deal! How about we modify the class at runtime? Ruby has this neat mixins feature which allows classes to be modified at any time. Here goes:
class MessageBox
def self.wide_show(msg)
MessageBox.show msg, 'This message box is ' + ('very ' * 8) +
' wide, is it not?'
end
end
MessageBox.wide_show 'Testing 123...'
… and we now have a customized “extra wide” MessageBox at our disposal
As you may have already figured out, we extended the MessageBox class, “def” defines a function, and the putting the “self.” prefix is similar to using “static” or “shared” in .NET. It makes it a “class method”
WPF
Quit out of irrb (type “quit:), start it up again afresh (“iirb”). Copy and paste the following:
require 'PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
require 'PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
require 'PresentationFramework, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35'
require 'PresentationCore, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35'
Windows = System::Windows
Media = Windows::Media
redBrush = Media::SolidColorBrush.new( Media::Colors.Red )
blackBrush = Media::SolidColorBrush.new( Media::Colors.Black )
redButton = Windows::Controls::Button.new
redButton.content = "Do NOT press!"
redButton.font_size = 40
redButton.font_weight = Windows::FontWeights.bold
redButton.Width = 600
redButton.Height = 400
redButton.background = redBrush
redButton.click do |sender, args|
Windows::MessageBox.show 'Please do not press this button again!',
'Why would you even do that?!?',
Windows::MessageBoxButton.OK, Windows::MessageBoxImage.exclamation
end
warningWindow = Windows::Window.new
warningWindow.content = redButton
warningWindow.title = "Example WPF Window"
warningWindow.background = blackBrush
app = Windows::Application.new
app.run warningWindow
Yep, this demonstrates how you can create a WPF window on the fly:
One last thing for this segment, the DLR is designed so that programs hosted on it can interact with each other regardless of which languages the different parts are written in. There is a rather cool Silverlight sample out there called “DLRConsole” which demonstates how you can modify Silverlight elements from IronRuby or IronPython in the same browser window.
This is the URL:
http://silverlight.net/content/samples/sl2/dlrconsole/index.html
Note: it could move at any time without warning. Just google on “DLRConsole” if this happens.
In Part 3 we will have at a partical use for IronRuby, BDD with Cucumber
This tutorial is based on a short demo/talk I gave at the Columbus .NET Developers Group (CONDG) on IronRuby. It’s mostly designed for the .NET professional and making no assumptions of prior Ruby experience.
In Part 1 we get everything installed.
In Part 2 we take IronRuby for a test drive
In Part 3 we use it to integrate with Cucumber.
Installing IronRuby
Before we get started, my instructions are more or less the same as this:
http://wiki.github.com/aslakhellesoy/cucumber/ironruby-and-net
… but with a little bit more elaboration on how to install the MRI and IronRuby.
If you already have it all installed, go straight to Part 2!
Step 1 – Install MRI (Matz’s Ruby Interpreter)
We will need the standard Ruby language installed so we have access to the Gems package installer. This makes it really easy to install additional Ruby libraries, like Rails and Cucumber.
Install the latest stable Windows version of Ruby from here:
http://www.ruby-lang.org/en/downloads/
I used the one click installer. At the time of writing the one-click installer installs Ruby 1.8.6.
Afterwards make sure you have the Ruby bin folder in your system path (It will probably be C:\Ruby\Bin):

Step 2 – Install IronRuby
IronRuby is currently available on Codeplex and Github. Grabbing it from Codeplex is probably the easiest approach:
http://ironruby.net/Download
This will allow you to download the MSI Installer version. The current installer at this time or writing is ironruby-0.9.2.msi.
Also make sure IronRuby’s bin folder is now in the system path (mine is called C:\Program Files\IronRuby 0.9.2\bin):
Step 3 – Install Cucumber
The cucumber installation instructions on the Cucumber Github wiki are here:
http://wiki.github.com/aslakhellesoy/cucumber/ironruby-and-net
I can’t really improve much on these remaining instructions. Just open a command prompt and do everything it says, with the exception of downloading and installing MRI and IronRuby. So just run all the commands, and create the icucumber.bat script file.
Our version will probably look more like this:
|
ECHO OFF
REM This is to tell IronRuby where to find gems.
SET GEM_PATH=c:\ruby\lib\ruby\gems\1.8
@ "C:\Program Files\IronRuby 0.9.2\bin\ir.exe" "c:\ruby\bin\cucumber" %* --no-color
|
NOTE: The --no-color option is a workaround for an issue with showing color in command terminals that exists in ruby at the moment on windows. You can try it with colors turned ont, but if its not fixed you will start seeing “←[36” symbols all your cucumber test output.
In Part 2 we will have a quick look at what you can achieve with IronRuby.