Ivan Porto Carrero

IO(thoughts) flatMap (_.propagandize)

21

May
2009

Getting Started With Caricature and IronRuby

IronRuby 0.5 was released yesterday. You can download it on codeplex. This post will explain how you setup your ironruby environment to use it for testing existing CLR based assemblies. We’ll touch installing gems using rake and most importantly writing a test for a CLR based class where we’ll mock out the dependencies.

The first thing you need to do is download IronRuby. After downloading you can extract it to a location on your hard drive. I extracted mine to C:\ironruby

Now we need to add the path to ir.exe to our PATH variable so we can use it from the command-line. And that is all there is to it to install ironruby on your machine. Now we need to get the necessary gems onto our system. We’ll need bacon and caricature.

Open a console and type the following:

igem list will show you a list of the gems you have installed on your system.

igem install will fetch and install a gem on your system. To install the gems we’re going to need we need to execute the command

igem install bacon caricature

That will result in the following output:

+ C:\tools
» cmd
Microsoft Windows [Version 6.1.7100]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\tools>where ir
C:\ironruby\bin\ir.exe

C:\tools>exit
+ C:\tools
» igem list

*** LOCAL GEMS ***


+ C:\tools
» igem install bacon caricature
Successfully installed bacon-1.1.0
Successfully installed caricature-0.6.0
3 gems installed
Installing ri documentation for bacon-1.1.0...
Installing ri documentation for caricature-0.6.0...
Installing RDoc documentation for bacon-1.1.0...
Installing RDoc documentation for caricature-0.6.0...

If you would try to execute ibacon at this point that would work. We’ll need to create 2 small files to get ibacon to work. In the bin directory of ironruby I created 2 files one called ibacon and the other one is ibacon.bat

ibacon
#!C:/ironruby/bin/ir.exe
#
# This file was generated by RubyGems.
#
# The application 'bacon' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'rubygems'

version = ">= 0"

if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
  version = $1
  ARGV.shift
end

gem 'bacon', version
load 'bacon'
ibacon.bat
@ECHO OFF

@"ir.exe" "%~dpn0" %*

At this point you’re ready to start writing specs with bacon and caricature. Let’s look at an example I wrote for the controller factory for ironruby mvc.

We’re going to test the following C# code.

Models.cs
public interface IWeapon{
    int Attack(IWarrior warrior);
    int Damage();
}

public interface IWarrior
{
    int Id { get; }
    string Name { get; set; }
    bool IsKilledBy(IWeapon weapon);
    int Attack(IWarrior target, IWeapon weapon);
    int SurviveAttackWith(IWeapon weapon);
}

public class Sword : IWeapon
{

    public int Attack(IWarrior warrior){
        return warrior.SurviveAttackWith(this);
    }

    public int Damage(){
        return 4;
    }
}

I generally create a bacon_helper.rb file where I group my requires and helper functions etc. In the case of this test I have the following in the bacon_helper.rb:

bacon_helper.rb
# add some search paths to ironruby
# this first one adds the path with the assemblies
# this enables us not to have to specify a path to the assemblies everywhere.
$: << File.dirname(__FILE__) + "/bin"
# adds the path to the caricature library.
$: << File.dirname(__FILE__) + "/../lib"

# load the caricature library
require "caricature"
require 'caricature/clr'

# load the bacon library
require 'bacon'

# Add the .NET framework
require 'mscorlib'

# load the assembly with the C# code
load_assembly 'ClrModels'

At this point we’re ready to start writing the test. create a file called sword_spec.rb and we’ll add the following content to the file.

swordspec.rb
require File.dirname(__FILE__) + "/bacon_helper.rb"

describe "ClrModels::Sword" do

  before do
    @warrior = Caricature::Isolation.for ClrModels::IWarrior
  end

  it "should call survive_attack on the mock" do
    @warrior.when_receiving(:survive_attack_with).return(5)

    sword = ClrModels::Sword.new
    sword.attack(@warrior).should.equal 5

    @warrior.did_receive?(:survive_attack_with).should.be.successful
  end

  it "should return different results when expectation is defined with arguments" do
    sword1 = ClrModels::Sword.new
    sword2 = ClrModels::Sword.new

    @warrior.when_receiving(:survive_attack_with).return(5)
    @warrior.when_receiving(:survive_attack_with).with(sword2).return(15)

    sword1.attack(@warrior).should.equal 5
    sword2.attack(@warrior).should.equal 15

    @warrior.did_receive?(:survive_attack_with).with(sword2).should.be.successful
  end

end

So now we’ve got 2 tests for our Sword class. The only thing that is left to do is to run the specs. You can do that by executing the ibacon command and passing it the file you want to test.

+ C:\dev\caricature
(master) » ibacon spec/sword_spec.rb
ClrModels::Sword
- should call survive_attack on the mock
- should return different results when expectation is defined with arguments

2 specifications (5 requirements), 0 failures, 0 errors

Comments

To top