Showing posts with label IronRuby. Show all posts
Showing posts with label IronRuby. Show all posts

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"


3. Dragons ahead. Use diversion

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\Lang
    uages\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 OFF
REM 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 COMPILE
MKDIR bin
:COMPILE
csc /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.dll
require 'BowlingGame'

Given /^I am starting a new game$/ do
# CHANGE 3 : Use Namespace::ClassName.new
@game = CukesDemo::BowlingGame.new
end

When /^I roll (\d+) gutter balls$/ do |count|
count.to_i.times{
@game.roll(0)
}
end

Then /^the score should be (\d+)$/ do |expected_score|
@game.score.should == expected_score.to_i
end

Then /^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 == true
end

When /^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 !!!
[Cukes_06.jpg]

HTH