Testing .NET Applications Using IronRuby
IronRuby is a Ruby implementation that is written on top of the .NET framework. It runs on top of the DLR (Dynamic Language Runtime), the bridge between the .NET framework and the dynamic languages that are written on top of it.
The main goal of IronRuby is to provide seamless integration with .NET objects that is achieved in a very elegant way; to work with a .NET assembly, just load it using Ruby’s require method (similar to adding a reference in C#/VB.NET).
For example, assuming you have the next C# class that features two methods which indicate whether a given time is daytime or nighttime and it is saved in an assembly named CustomTools.dll:
using System; namespace CustomTools { public class DayNightHelper { public bool IsDay(DateTime value) { if (value.Hour > 7 && value.Hour < 19) return true; else return false; } public bool IsNight(DateTime value) { bool isDay = IsDay(value); return !isDay; } } }
Using this class from IronRuby is easy as pie:
require "DayNightHelper.dll" # Call C# class constructor helper = CustomTools::DayNightHelper.new # Call C# method day = helper.is_day(Time.now) if day then puts "The sun is in the sky, go out!" else puts "Good night!" end
Because calling .NET assemblies is so easy from IronRuby code, it enables developers to take advantage of Ruby’s libraries and frameworks together with .NET assemblies, and make the most out of this combination.
One of the areas that pops to my mind instantly, which makes the Ruby/.NET combination shine the most, is using Ruby’s incredible testing frameworks to test .NET code.
In this article, I will introduce three of Ruby’s testing frameworksRSpec, Cucumber, and riotand show you how to use them to test .NET code.
RSpec
RSpec is one of the most popular testing frameworks in Ruby, if not the top one. It follows BDD (Behavior Driven Development) principles, a fact that reflects on its terms. Basically, in RSpec you separate your tests into behaviors which are the test containers. Every behavior contains multiple examples, which are the test methods. The logic behind the terms is to give you the illusion that you do not test codeyou validate behavior.
RSpec provides a DSL (Domain Specific Language) for tests that result in clean and elegant test code. A behavior is contained within a method named describe. This method receives a textual description of the behavior or a class type, if a single class is being tested. Inside the describe call body, you can add multiple examples via a method named it. This method receives a textual description as well, and contains the actual test code. In addition, every example must have some kind of comparison between the expected result and the actual one. This is done with the should method, which is added to all Ruby objects.
For example, a simple RSpec code to validate the behavior of the DayNightHelper class is as follows. Notice the clean code:
require "DayNightHelper.dll" # The following require statements are needed for RSpec to run require "rubygems" require "spec" require "spec/autorun" # Define a behavior with describe describe "Test DayNightHelper class for perfection" do # Define examples with it it "should be day on 15:00" do instance = CustomTools::DayNightHelper.new result = instance.is_day(Time.local(2012,12,21,15,0)) # Compare actual and expected result with should result.should == true end it "should not be night on 15:00" do instance = CustomTools::DayNightHelper.new result = instance.is_night(Time.local(2012,12,21,15,0)) # There are also some cool methods to do common comparisons. # For example, the next line is identical to "result.should == false": result.should be_false end end
Executing behaviors is done from the command line using the IronRuby interpreter: ir.exe. Assuming the RSpec code is located in a file named rspec_test.rb, executing it will be done as follows:
>ir rspec_test.rb .. Finished in 0.168009 seconds 2 examples, 0 failures
It is also possible to show the textual descriptions of the behavior and examples in the report by using --format s:
>ir rspec_test.rb --format s Test DayNightHelper class for perfection - should be day on 15:00 - should not be night on 15:00 Finished in 0.158009 seconds 2 examples, 0 failures
What I brought you here is only a taste of RSpec capabilities. To learn more about it, visit the RSpec official site.