A couple of days ago I was requested politely and with acknowledgement of my humanity, by Dr Nic to write a post about testing gems on 1.9 and because he’s my boss I’m obliged to do the things he tells me to do. He told me to read his post about Future-proofing Your Ruby Code and in particular the instructions about installing multiruby.

How to install multiruby

You can install multiruby, different versions of ruby, rubygems and useful gems using these commands:

sudo gem install ZenTest
multiruby_setup mri:svn:tag:v1_8_6_114
multiruby_setup mri:svn:tag:v1_8_7_153
multiruby_setup mri:svn:tag:v1_9_1_0

multiruby_setup update:rubygems
multiruby -S gem install --no-ri --no-rdoc --development test-unit

This will:

  1. Install ZenTest (or the latest version)
  2. Install Ruby 1.8.6, build 114
  3. Install Ruby 1.8.7, build 153
  4. Install Ruby 1.9.1, build 0
  5. Setup Rubygems for all three versions and;
  6. install test-unit for all three versions!

You may also want to multiruby -S gem install –no-ri –no-rdoc –development rails mocha rspec.

multiruby is awesome because it sticks this all in your home directory in a folder called .multiruby, so don’t worry about it clashing with your existing version(s) of ruby. Different versions go in different directories inside .multiruby/versions.

numero!

Today we’re going to be testing a gem that I recently made use of on this site. For those of you that visited the site yesterday you would’ve seen something like this:

  112.117.116.115.32.34.104.101.108.108.111.32.119.111.114.108.100.34

This is numero! (exclamation mark compulsory). I don’t know where the idea came from. According to the MSN logs I keep, at 8:03am Friday morning I went and made breakfast and then at 8:13am I had the idea. But it’s awesome. The “language” uses the ASCII representation of all your favourite characters and separates them using a dot. This is numero! script. You run it using the numero! gem. This is how you get it:

sudo gem install radar-numero --source http://gems.github.com

Test it out by running it on your favourite ruby script!

numero favourite.rb

This will generate a file called favourite.numero and then evaluate the newly generated numero! code. Now you can throw away your ugly ruby file and bathe in the glory that is numero by then running:

numero favourite.numero

So it appears we’ve gone off on a tangent here! Fear not! For I want you to test my gem on your new multiruby setup:

git clone git://github.com/radar/numero
cd numero
git checkout -b broken origin/broken

Now this sensible naming schema will probably dissolve the mystery surrounding what’s going to happen next. You’re going to be testing my gem, and it’s going to break.

Testing numero!

When I wrote this particular branch of numero!, I used “a”[0] to get the ASCII representation (97) of the letter a. Generally, I would’ve used use a variable rather than “a”, but this is just an example. The problem is that this doesn’t work the same way in Ruby 1.8.* and Ruby 1.9. If we run multiruby -S test/test_numero.rb we see that it passes on both versions of Ruby 1.8, but fails on Ruby 1.9!

Ruby 1.8.*

Loaded suite test/test_numero
Started
.
Finished in 0.001186 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

Ruby 1.9 Loaded suite test/test_numero Started F

Finished in 0.025228 seconds.

1) Failure: test_numero_compiles(TestNumero) [test/test_numero.rb:9]: <”["p.u.t.s. .\".h.e.l.l.o. .w.o.r.l.d.\""]”> expected but was <”112.117.116.115.32.34.104.101.108.108.111.32.119.111.114.108.100.34”>.

1 tests, 1 assertions, 1 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications </pre>

Not good! This is something I wouldn’t have found if I didn’t test the functionality on multiple Rubies. Using multiruby is essential to ensure that your code works for everybody. We don’t want to end up like Internet Explorer.

The solution, of course, is to use str.unpack(“C”).first instead. You have two options: 1) change the code yourself in lib/numero.rb to use the afore-mentioned example or 2) git checkout master. Now we run the tests again and now Ruby 1.9 passes:

Ruby 1.8.7

Finished in 0.001109 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

Ruby 1.9.1

Finished in 0.001353 seconds.

1 tests, 1 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications

Lovely!