Greg Malcolm,

Software Vandal

  Home  |   Contact  |   Syndication    |   Login
  12 Posts | 0 Stories | 10 Comments | 0 Trackbacks

News

A waterpark in January... The only way to write code

Twitter












Archives

Thursday, November 05, 2009 #

<< 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:

http://github.com/gregmalcolm/IronPoker

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:
 
IronPoker Stub App Screenshot

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):
 
1st Cucumber Test Results Screenshot

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).
 
Initial Implementation Screenshot

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:

Hand.methods Screenshot 

There they are! Only because the function names have been rubyized, they have become add_card and eval_score.

Let try playing a hand:
 
Straight Flush in IIRB Screenshot

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:
 
Implemented Tests Screenshot

Save that and we can run our cucumber test again:

 
Failed Test Screenshot

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:

 Completed Tests Screenshot

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.

DLR Diagram

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>:

IIRB Prompt Screenshot 

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:
IIRB showing ruby commands executed screenshot
 
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:

http://tryruby.sophrinix.com/
http://ruby-doc.org/docs/ProgrammingRuby/


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:
 
MessageBox screenshot

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
 
Wide Messagebox Screenshot

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:

 
WPF Screenshot

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.

DLR Console

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.

Installer In Part 1 we get everything installed.

IIRB In Part 2 we take IronRuby for a test drive

Cucumber 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):

 Ruby Path Screenshot



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):

 IronRuby Path Screenshot



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.