Testing .net with IronRuby’s mini_rspec.rb

The IronRuby team has uses a couple facilities to test their own implementation of the Ruby language. simple_test.rb which resembles a Test::Unit type of framework with less baked in, and minispec by Brian Ford of the RubySpec project. (Thanks Charles for pointing out my error, sorry Brian for the wrong attribution). Minispec and RubySpec allow ruby implementations to test their compatibility among a common set of of specs produced by the RubySpec team. This allows the IronRuby team to run the same specs against Ruby, as well as run them directly through rbx.exe, the IronRuby interpreter. Once you get and compile IronRuby, you can see they have also created rake tasks to run the specs in a few scenarios. Here is the output of rake -T | grep spec.

rake rspec # run specs using Ruby - params are: class [method(…

rake spec # run specs - params are: class [method(s)] [reporter]

rake spec2 # run specs using IronRuby and Ruby - params are: c…

rake specs # run Ruby spec suite

So running rake spec from the command line will run all of the IronRuby specs through rbx. If you would like to take a look at all of these, the mini_spec framework is in %IronRubyRoot%\tests\ironruby\specs and all of the specs are in %IronRubyRoot%\tests\ironruby\specs\core.

One of the use cases I see IronRuby excelling at is writing unit tests. I’m a huge fan of RhinoMocks and NUnit, and am able to get a ton done with these tools, but after looking at testing in Ruby I’m always jealous of the tools the test centric Ruby community has at their disposal. There is no lack of elegant testing frameworks, tools, and practices on this side of the fence. Hopefully a good portion of them, if not all of them, will eventually make it over to IronRuby, but for now you can use these mini frameworks to test your .net code.

Disclaimer time, IronRuby is not even an alpha yet. Relying on these frameworks to do anything more then oooo look at me I’m testing .net with IronRuby demonstrations and practice is not suggested.

So on to the code. Let’s assume you are building a system that requires a person, and this person has a first and a last name. Imagine you have an class that represents that person that looks something like, or exactly like :

Code (c)
  1.  
  2. public class Person
  3.   {
  4.     public string FirstName { get; set; }
  5.     public string LastName { get; set; }
  6.     public string FullName
  7.     {
  8.       get { return string.Format("{0} {1}", FirstName, LastName); }
  9.     }
  10.     public int Age { get; set;}
  11.     public int AgeInDays
  12.     {
  13.       get { return Age*365; }
  14.     }
  15.   }

This complicated code MUST be tested. Below is some IronRuby code that works today that will test the class above. It looks like :

Code (ruby)
  1.  
  2. require ‘C:\projects\IronRuby\trunk\tests\ironruby\Specs\spec_helper’
  3. require ‘c:\PathToMyDll\Person.dll
  4. Nsp = NameSpaceThatTheAboveClassIsIn
  5.  
  6. describe ‘Nsp::Person’ do
  7.  
  8.   before :each do
  9.     @person = Nsp::Person.new
  10.   end
  11.  
  12.   it "should concatenate name" do
  13.     @person.first_name = "Bill"
  14.     @person.last_name = "Smith"
  15.     @person.full_name.to_str.should == "Bill Smith"
  16.   end
  17.  
  18.   it "should be able to calculate age in days" do
  19.     @person.age = 1
  20.     @person.age_in_days.should == 365
  21.   end
  22. end

That works today. Being a big fan of the spec syntax, I think this test reads very well, much less clutter then in a typical xUnit test.

Walking through the test, notice that we first bring in and alias the external resources we will need. Then we dive into a describe block that sets the initial context of the test. The describe method will either take a type or a string, but did not seem to like taking a .net type yet. Then we have a before filter that will be run before each test, setting initial state for the contexts below. Then we have a number of it blocks where specific tests are performed. Notice that once we have a Person instance, we can address it’s variables via Ruby conventions. My C# class has a FirstName property, but I can use the first_name convention in IronRuby, smooth.

Also of note, notice I had to call .to_str on @person.full_name. This is due to the fact that IronRuby string != CLR Strings as of yet. A recent thread on the mailing list reminds us all that the team will be fixing this later, but calling to_str will work.

Will I be doing this at work? Not yet, but the idea of using Ruby test tools to test my .net things is very appealing to me. Less cruft, mocking and stubbing should be a lot easier, and tools like AutoTest will change how I do TDD in .net if things come together as I am imagining.


You can follow any responses to this entry through the RSS 2.0 feed. You can skip to the end and leave a response. Pinging is currently not allowed.

4 Responses to “Testing .net with IronRuby’s mini_rspec.rb”

  1. Hey Aaron, this is a great writeup! Thanks!

    I’m very excited to use specs in Ruby to test my C# code. I hope we eventually see a CLR-based equivalent to Ola Bini’s JTestR library.

    http://jtestr.codehaus.org/

  2. I hate to nitpick, but minispec is the creation of Brian Ford, of the RubySpec project. Brian and the RubySpec contributors have been doing an amazing job writing specifications for the Ruby language and its core classes and libraries, and minispec has made it possible for even early implementations to run those specs. Rubinius uses RubySpec exclusively and we on the JRuby project include it as one of the many test suites we run.

  3. Wow, great catch Charlie! I reread the article and it does sound like minispec was attributed to the IronRuby team. RubySpec is awesome and should definitely have more eyes on it. I feel bad for skimming over that earlier.

  4. Charles : Not nitpicking at all. Thank you very much for pointing out my error. I will correct the post now.

    Mike : Something like jtestr for .net things would be fantastic. I’m really excited to see where we can go with testing in IronRuby.

Leave a Reply