Posts Tagged ‘testing’

Testing Gems with multiruby

Thursday, April 2nd, 2009

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: testnumerocompiles(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

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!

Webrat Woes

Friday, January 30th, 2009

Yesterday I wrote a feature for one of the apps at work that was fairly simple it contained this line:

  clicks_link("I am done")

The page contained a link with the text exactly as “I am done” and in all dimensions of this universe you would expect this to pass without fault. It didn’t.

So when this feature failed I brought Bo over and got him to look at it. We couldn’t figure it out yesterday and it took a few hours this morning to figure out what it was. The site was fairly basic, consisting of a layout that contained:

<%= link_to "Things", thing_path %>
<%= yield %>

And the page itself consisted of a form and ended in the link:

<%= link_to "I am done", do_something_path %>

But the bloody feature failed! So we sanity check’d it, output the response’s body and definitely saw the a tag in there. It was there! So we further checked it and tried the URL from the layout and that worked! Major WTF moment there. It took us an hour or so of further WTF before Bo said “Humour me” and gave the layout valid HTML, you know, something like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
  <%= link_to "Things", things_path %>
  <%= yield %>
</body>
</html>

And the feature passed! So remember kids, do not be lazy! If you’re testing with webrat remember to always have a valid HTML layout on your site!

Faking It

Monday, July 14th, 2008

Today I was doing the one thing I truly, truly love doing and that’s complaining about writing RSpec tests. I came across a doozy of a problem involving RSpec testing and faking subdomains. Here’s a stripped down version of what I did:

def login_as(user)
  session["user"] = users(user).id
  request.host = User.find(session["user"]).company.domain + ".example.com"
end

Just pop that into your spec/spechelper.rb and then you can use loginas(:user) which will find the fixture with the name of “user” and then go from there to setting your faked host as being from, for example, blah.example.com.

Pretty simple, shame Google didn’t turn up any relevant results without me having to dig deeper than usual.

Testing: There Has To Be A Better Way

Friday, January 11th, 2008

I hate testing in Ruby on Rails. I hate writing tests, and I especially hate running them. At work, we have 618 examples and it takes 346 seconds to run. That’s 5 minutes and 46 seconds to run 6000 lines of code, it’s pathetic!

The reason for this is that we have a central object which a lot of other objects are related to, called booking. Now, without giving too much away I’ll say that, along with the bookings table, there are 8 other tables that are emptied and loaded with data during a large majority of the tests. All this emptying and refilling is taking time, time that could be better spent not waiting for the tests to finish!

This is why I propose a system that entirely relies on fixtures for its data supply, so it doesn’t have to empty & load the tables again and again, but instead reads directly from the fixture files every time. I have no idea how to go about making one, but if anyone reads this and wants to collaborate with me on something like it, by all means please do. I hate having to read my emails whilst waiting for the tests to finish, I run out of emails.