### Testing .Net code with Cucumber and IronRuby

As promised, this is the culmination of this trilogy. The previous two posts were a jump-start on Cucumber to test Ruby code. Next I moved towards using Cucumber's plain text stories to test .Net code.Aslak Hellesoy has a wiki-post on how to do this ; however I found that you get eaten and spat out by a lot of IronRuby dragons along the way. So hold on..

1. Install the new DLR

First up install .Net Framework 4.0 (I have Beta1) - this has the new Dynamic Language Runtime (DLR) that makes things like IronRuby and IronPython possible.

2. Get the latest IronRuby release

Next we need to get IronRuby as a zip. Extract it to say d:\ironruby-0.9.0 Add the path to the bin folder to your PATH environment variable to avoiding lengthy paths. Drop to a command shell, type 'ir' to invoke the interactive IronRuby console. Type something simple to test if it works. It should.
>>>puts "Hello IronRuby"

But I hit a snag with this version of IronRuby, which had A BUG.

• So I had to get the latest (8 Sep 2009 master to be precise) version of the source from the github repository to overcome that. You can download it as a zip or use git as you prefer. I got the zip
ironruby-ironruby-90cdda82fd60f4b7e6d7d940501c586d55954466.zip (Could have used a shorter name)

• Extract it to say d:\ir-src
I hit a few path-too-long errors during extraction. Just keep skipping them. I think it's because of the rather large alphanumeric string which is the name of the top-level folder.

• Once extracted, navigate to D:\ir-src\ironruby-ironruby-90cdda82fd60f4b7e6d7d940501c586d55954466\Merlin\Main\Languages\Ruby
and open Ruby.sln in VS2008 (I have Dev Edition of VSTS.. Although it should build in VS Express Editions as per the docs - I couldn't get the solution to open in it.)
Build Solution. At the end of it you should find the built binaries in
D:\ir-src\ironruby-ironruby-90cdda82fd60f4b7e6d7d940501c586d55954466\Merlin\Main\bin\Debug

• Rename that directory with the huge name to something like "ir".

• Copy all built binaries and overwrite the ones from the 0.9.0 release's bin folder i.e. D:\ironruby-0.9.0\bin.

• Open ir.exe.config in the same folder and update the Library paths element to the proper paths to folders within your ir-src folder. 'Handle with extreme care' or you'll lose hours chasing error messages. It should read
Path#1 - D:\ir-src\ir\Merlin\Main\Languages\ (NOT D:\ir-src\ir\Merlin\External.LCA_RESTRICTED\Languages)
Path#2 & #3 - D:\ir-src\ir\Merlin\External.LCA_RESTRICTED

My xml looks like
<set language="Ruby" option="LibraryPaths" value="D:\ir-src\ir\Merlin\Main\Languages\Ruby\libs\;D:\ir-src\ir\Merlin\External.LCA_RESTRICTED\Languages\Ruby\redist-libs\ruby\site_ruby\1.8\;D:\ir-src\ir\Merlin\External.LCA_RESTRICTED\Languages\Ruby\redist-libs\ruby\1.8\" />

4. Wrapper script ICucumber

Lastly we need a wrapper script to invoke cucumber with Ironruby. Create a file called icucumber.bat under your Ruby bin folder i.e. D:\Ruby\bin\icucumber.bat with the following text.

REM Update with appropriate values for GEM_PATH, Ruby bin and the path to ir.exe@ECHO OFFREM This is to tell IronRuby where to find gems.SET GEM_PATH=d:\ruby\lib\ruby\gems\1.8"D:\ironruby-0.9.0\bin\ir.exe" -D -X:ExceptionDetail "d:\ruby\bin\cucumber" %*

5. Back to our example from the previous two posts.
The .feature file stays unchanged.
Delete c:\cukes\dot_net_features\support\BowlingGame.rb ; since we're going to implement the same in C# this time around as
c:\cukes\dot_net_features\support\BowlingGame.cs

namespace CukesDemo{   public class BowlingGame   {      public void roll(int pins_knocked_down)      {        Score += pins_knocked_down;      }      public int Score      {         get; set;      }      public bool Over      {         get { return false; }      }   }}

Also create a small batch file to compile it to a DLL (Assumes csharp compiler is on the PATH).
c:\cukes\dot_net_features\support\Compile.bat

IF EXIST bin GOTO COMPILEMKDIR bin:COMPILEcsc /t:library /out:bin/BowlingGame.dll bowling_game.cs

Finally back to our step definitions to check the glue. Four changes needed - explained in comments.
cukes\dot_net_features\step_definitions\bowling_game_steps.rb

# CHANGE 1 : Add bin folder to load-path$:.unshift(File.dirname(__FILE__) + '/../support/bin') # CHANGE 2 : Get BowlingGame.dllrequire 'BowlingGame' Given /^I am starting a new game$/ do   # CHANGE 3 : Use Namespace::ClassName.new     @game = CukesDemo::BowlingGame.new   endWhen /^I roll (\d+) gutter balls$/ do |count| count.to_i.times{ @game.roll(0) }endThen /^the score should be (\d+)$/ do |expected_score|  @game.score.should == expected_score.to_iendThen /^the game should be over$/ do # CHANGE 4 : be_over passes even if Over returns false. Don't know what is the equiv of over? in .Net #~ @game.should be_over == true @game.over.should == trueendWhen /^my rolls are (.*)$/ do |rolls|  rolls.split(' ').each{|roll|    @game.roll(roll.to_i)  }end

Now for the grand finale, run Cucumber to verify our .Net DLL via IronRuby !!!

HTH