Archive for the 'Ruby on Rails and Software Development' Category

Using Cucumber to estimate a project

Friday, May 15th, 2009

InvoiceWriting estimates up-front is a really tricky part of client work.

From the customer’s point of view it’s pretty essential. You need to know how much you are spending before the work begins so you don’t get stung.

From the developer’s point of view it’s pretty difficult to do because you don’t know how long things will take until you know what you’re building. And you don’t know the details of what you are building until they become apparent, which is normally while you are doing the work.

For this particular client I wanted to get this piece of work out of the way as quickly as possible and the requirements were deceptively complicated. As trying to deal with intangibles is a recipe for disaster, and time was short, I was pretty sure that whatever estimate I came up with would be totally inaccurate.

So to deal with the intangibles I thought I may as well get stuck in with the actual work. And what’s the first thing that I do? Write a cucumber story.

I went through the requirements documents (which after weeks of to and fro were actually quite detailed and refined) and broke it down into four features, each with a number of scenarios. Each scenario was then broken down into individual steps – however, I did not write any step definition (ruby) files. This is cucumber as customer documentation, not as integration testing.

We agreed that the features met the requirements (the client was very impressed with the level of detail and the clarity that cucumber offered) and I simply went through each feature, scenario and step and came up with a price for the step individually. It’s still guesswork, but it’s guesswork on a small scale, so you’re less likely to be way off. Total the lot and there’s your estimate.

And even better, once the client has agreed the price and you’ve started development, you’ve got a development plan, a measure of progress and proof that it all works – all just a simple rake features away.

Image by lemon drop

Switching off transactions for a single spec when using RSpec

Friday, May 8th, 2009

I have just written a load of test code that needed to verify that a particular set of classes behaved correctly when a transaction was rolled back.

However, the rest of my suite relied on transactional fixtures (which is Rails’ badly named way of saying that a transaction is started before each test and rolled back at the end, leaving your test database in a pristine state before the next case is run).

In particular, my spec_helper.rb had the following:

Spec::Runner.configure do |config|
  config.use_transactional_fixtures = true
  # stuff
end

The code being tested looked something like this:

begin
  Model.transaction do
    do_something # may fail with an exception
    do_something_else # may fail with an exception
  end
rescue Exception => ex
  do_some_recovery_stuff
end

I had a spec for the successful path (checking that the outcomes of do_something and do_something_else were what I expected.

However when I tried the same for the failure paths, the outcomes matched the successful path. The time-tested debugging method of sticking some puts statements in various methods showed that do_some_recovery_stuff was being called as expected. But the outcomes were still wrong.

And the reason? Transactions. This was a Rails 2.2 project, running on Mysql (innodb). As RSpec/Test::Unit starts a transaction before the specification clause runs (and then rolls it back on completion) when Model.transaction statement is reached, the spec is actually starting a second transaction, nested within RSpec/Test:Unit’s. Which means when the inner transaction is rolled back, the database doesn’t actually do anything – there’s still an outer transaction that may or may not be rolled back. (I think Rails 2.3 corrects this behaviour and if you roll back an inner transaction then the outer transaction reflects the correct state, but I’m not 100% on that).

So I had a choice – move the (production) app to Rails 2.3 to fix this one bug (which is very urgent) or figure out how to switch the outer transaction off for these particular steps. Google wasn’t very helpful – lots of stuff on how RSpec extends Test::Unit, lots of stuff on how Rails extends Test::Unit to add the fixtures (and transaction) support. But no concrete example on how to actually switch it off.

After much playing around (overriding methods like use_transaction?(method_name) and runs_in_transaction?) I eventually stumbled across the answer. And it’s pretty simple.

Set your default to be config.use_transactional_fixtures = true in spec_helper.rb. Then, for the specs that are not transactional, simply create a describe block and simply add the following:

describe MyClass, "when doing its stuff" do
  self.use_transactional_fixtures = false
  it "should do this"
  it "should do that"
  it "should do the other"  
end

The only thing to be aware of is you may well need an after :each block to clean up after yourself.

Fixing bugs in untested code

Wednesday, May 6th, 2009

When you’ve got an application that has little or no test coverage it can be quite daunting making changes. What if you alter X and it breaks Y? Without running through the entire app by hand how will you know what you’ve broken?

Well you won’t.

Even worse, what if your client reports a bug in that application? That makes things even worse doesn’t it?

No. It’s actually an opportunity. Because even if your boss thinks “testing is a great idea, we’ll start on the next project when we’ve got more time”, a bug fix is one of those things where the time to fix varies. So take advantage of that.

Start by writing a test that reproduces some functionality in the same area that you know works.

This won’t be easy. You need to get the database into the correct state, set up the session correctly. To save you some time, try using an object factory – with the correct configuration you can concentrate on creating just the models you need without having to fill the entire database with test data.

Take a look at the code you are testing as you are writing the tests. But make sure your test checks the outcomes of that code, not the implementation – when using mocks it’s pretty easy to end up effectively rewriting the real code as a series of should_receive(:something) calls. Which looks great until you come to refactor, at which point it becomes a nightmare.

Get your test to pass. Remember this is a feature that works so it shouldn’t be that hard to get it to pass. And you are building some important foundations as you are setting up a configuration for your object factory a model at a time.

Once you’ve got the first test working, prove that it’s doing what it’s supposed to be doing. Comment out its of the implementation and watch it fail. If it doesn’t fail then you’ve got a problem – your test is testing something other than that particular implementation.

Now we’ve got a test that really checks your existing code. I like to add another test that checks the error handling in that existing code as well (there is error handling in your existing code isn’t there?) Follow the same process as before – test the outcomes (probably catching an exception if you’re at the model level, probably looking for a particular redirect and flash message at the controller level), and then prove that it works by commenting code out. Hopefully this should be pretty quick to write as most of the hard work was done when setting up the original test.

And finally we can get to the meat of it. Write a test that reproduces your bug (that is, your test exercises your app in the way expected and your app should fail). Again, most of your setup work should already be done, so it shouldn’t take too long. Now run the test and watch it fail. If it doesn’t fail then your test isn’t right.

After all of this, we are finally in a position to fix the bug.

Your test should prove that it’s been fixed. And prove that the bug won’t reappear in a future version. But you’ve also taken an important first step to wrapping your application in tests, making your life easier in future.

Bug of the day: cookie not being saved? Check your host-name.

Monday, April 27th, 2009

Lesson learnt today.

Apparently, underscores are not part of the standard for a host name. However, your browser (and DNS server and all the links in between) will accept underscores in the host name.

But, when you have Safari set to “only accept cookies for sites that I visit” the underscore in the cookie’s host will cause Safari to silently discard the cookie. Leaving you with a strange log-in bug that seems to defy explanation.

The solutions – make your host name compliant with the standard. And until you can do that, switch Safari to “accept all cookies”.

Moving to Coda

Wednesday, April 22nd, 2009

Tomorrow I’m actually going to do it.

I’m going to change the tools that I use to code in Ruby for the first time in four years. You see, I must be one of the very very few Ruby-programming Mac-users that doesn’t like Textmate.

This is pretty much heresy to most Rubyists.

I used to think I didn’t like Textmate because of the single window interface. Multiple windows could be positioned exactly where I want them (that window only has a couple of lines in it so I can keep that tiny and see both that and that other file at the same time). Tabs are all the same size for each file and you can’t keep them arranged as you want them.

But then I bought the MacHeist bundle. And got a little web-developer’s editor called Espresso. I really like MacRabbit’s CSSEdit so was looking forward to trying Espresso. And like it I did. I even got over my tabbed interface problems (maybe nicely styled tabs with a list view beats ugly tabs with a drawer). But there was a problem. Espresso is crap for Rails development (despite Elliott Cable’s ruby “sugar”).

So, having been spoilt by an “integrated” editor, but still not liking Textmate, where could I go? Coda, by Panic, was where. And I have to say I really like it. It’s not perfect, it’s taken me about a week to get my head round how things hang together. But it deals with ruby and rails and is extensible.

Which is enough to make me shell out the $99. And change the way I work pretty fundamentally.

Quick Tip: make it easier to debug your full-stack acceptance tests

Tuesday, March 24th, 2009

Spanner in the works

Spanner in the works

One of the issues when using Selenium or Watir to power your full-stack acceptance testing (apart from the time it takes for the test suite to run), is that stuff happens within your browser, fails and then Cucumber happily moves on to the next test before you get a chance to look at what went wrong.

If you are just using plain old Webrat you can pepper your code with puts statements so you can check the value of variables, the existence of HTML elements and the flow of code as it happens. But with Selenium or Watir, you need to run your app separately to Cucumber, normally in a hidden, background, process, so the output of your puts statements is lost in the ether (or an empty pipe).

After having a particularly annoying and hard to trace bug, that was related to an interaction between form content and javascript, I came up with an extremely simple debugging tool.

Just add the following into one of your steps files:

When /^I pause$/ do
  STDIN.gets
end

Then, find the feature that is causing you grief and insert a “when I pause” step at the appropriate time.

When I do this
And I do that
And I pause
And I press "Save"
Then I see my newly created object

Cucumber will power your app, poking it until it gets to the “when I pause” step. It will then pause, waiting on STDIN for you to hit return – giving you time to open your inspector window and poke around in the form as the tests see it.

In this particular case, my steps file had an incorrectly named element within it – all it took was an inspection of the element in question and I saw the error. Hours of frustration wiped out by one of the simplest commands there is.

Spanners by woodsy

Ruby 1.9 and gem compatibility

Thursday, February 5th, 2009

You may have heard that Ruby 1.9.1 is now out and “production-ready”.  This gives us a number of benefits, not least real threading and a general performance boost.  However, there is “production-ready” and there is “production-ready”; in particular, Ruby alone isn’t much use without the many gems that we all depend upon also being usable.  

So, we at Brightbox have just launched http://isitruby1.9.com; a community site that lets you mark gems as working or not.  It’s quick and easy and will really help people out so please test your favourite gem, then stop by and record the results.

Cucumber and WATIR: kick-starting your testing

Friday, January 16th, 2009

I think Cucumber is fast becoming indispensable for my testing. The point of it is that you can write documentation that your client understands and then prove that the application does what it says. When coupled with WATIR you can show that it really works in an actual browser – you can even show it in Internet Explorer, Firefox and Safari.

There are a number of issues with using WATIR – the main one being speed – as WATIR scripts the browser, an extensive test suite will take a long time to run.

But my first hurdle was actually getting the code running. Unlike using Cucumber with Webrat, where your Cucumber steps have access to your Rails code (so you can play around with the response object), with WATIR you run the application in a separate process and then poke the browser in the same way a real user would. Of course, unlike Webrat, you get to test your Javascript too.

However, I didn’t want to have to remember to start my application before running the tests (and probably forgetting to put it into the test environment or running on the wrong port) – so I came up with the following for your features/support/env.rb.


system 'rake db:test:clone'
system 'rm log/test.log'
system 'ruby script/server -p 3001 -e test -d'

at_exit do 
  system "kill `ps aux | grep mongrel_rails | grep -e '-p 3001' | grep -v grep | awk '{ print $2 }'`"
end

Before do
  @browser = Watir::Safari.new
  @browser.set_fast_speed
  @base_url = 'http://localhost:3001'
end

This clones your development database, gets rid of the test log (as we’ll need to look through that to track down any errors, so we want to keep it small) and then starts your app in test mode on port 3001 (so it doesn’t clash with the version you’ve already got open in development). The Before clause sets up WATIR and configures a base url that my steps use elsewhere. And the at_exit hook looks for the server we started and kills it.

Next step is to add a platform instruction – so you can choose to test with Safari, Firefox (if I can ever get the Firewatir plugin installed) and Internet Explorer (where I guess the kill statement will need a bit of alteration).

An alternative is to tell mongrel to start and write a pidfile to a known place, and then replace the ps/grep line with:


  pid = File.read(File.expand_path(RAILS_ROOT + "/log/mongrel.pid")).chomp
  `kill #{pid}`

Thanks to Caius for that version.

The curious case of beauty in Ruby (or Rails vs Merb part 2)

Saturday, December 27th, 2008

I’m sure you’ve all heard the Rails 3 announcement. When I first found out my initial reaction was “fuck me“. But shortly after I was filled with a feeling of dread and general unease. And I didn’t know why ….

Firstly, a bit of history.

I first tried programming on a Commodore Vic 20, and then after that a C64. C64 BASIC was very simple – if you wanted to do anything beyond PRINT statements you needed to POKE values into registers and control the hardware directly. Great for learning how things actually worked. And, to be fair, I was shit at it.

But I do remember reading an article on a system called “Smalltalk” and its “Object Oriented Programming”. Suddenly, programming made sense. It read a bit like English. You sent messages to the thing that knows how to answer your question. It was like talking to people. You ask Dave a football question. You ask George a music question. Cos Dave knows crap all about music and George knows nothing about football.

But, in those days, Smalltalk cost a fortune; there was no way a child like me could get hold of a Smalltalk environment. So instead, I got hold of Turbo Pascal 6 With Objects (thanks Dad). It was not Smalltalk but it read a bit like English and it had objects. I played about with Turbo Pascal, went to university (where I didn’t do computing but did do some C++) and then got a job doing Delphi (Turbo Pascal for the 90s). This object-oriented stuff really worked for me; I put a lot of effort into writing classes that had really simple public interfaces and with code that read like English. And Pascal (the language underlying Delphi) was great for that. Then I discovered Java, which meant I could write Delphi-like code but with having to deal with memory management. I also discovered PHP, Python and Ruby. None of which clicked with me; dynamic typing made me nervous (and PHP and Ruby seemed a bit ugly).

However, I needed an ORM for a Delphi project and I thought I should try to copy an open source project. Whilst searching I discovered Rails and thought “this is the one to copy”. But a day into my “copy ActiveRecord into Delphi” plan I thought “this is just like Smalltalk”. Why make an inferior copy when I can use something that’s not far off the Holy Grail. Writing an application on Rails had the same effect on me as my original discovery of Smalltalk – it read like English, it felt fantastic. So I gave up on Delphi and became a Rails programmer.

What I liked about Rails was its emphasis on happiness. When I wrote Rails code I felt like I was writing beautiful prose. I would go back and refactor it until it read correctly. This was not like pure Ruby, which was often ugly. No; Rails had this idea about beauty in code that really got me excited. It made me happy. It also made decisions for me – put your code here, test it like this, set up your database this way. But Rails had performance problems – so Merb was born. A ground-up rewrite of many of Rails’ ideas but with an emphasis on configurability and performance.

Maybe it’s the Engine Yard connection (I turned Engine Yard down for a job because it didn’t “feel right”) – and now I work for Brightbox, one of their competitors – but for some reason, every time I tried Merb I just couldn’t get into it. It was weird. Structurally and functionally it was the same as Rails – but it was Rails plus performance plus options. And I didn’t like it. I never got past the tutorials. Merb emphasises clear and understandable code and was tested with RSpec (which I love). Rails is hard to understand and uses Test::Unit (which is ugly). But I love Rails and I can’t get into Merb. I just couldn’t figure out why.

Until today.

Mr Hanson did a blog post on his first piece of Rails-Merb integration. And something stood out at me. As he was describing Merb’s provides/display functionality I noticed that I didn’t really “get it”. provides made sense, but how does that relate to display. Mr H addresses that directly:

There were a couple of drawbacks with the provides/display duo, though, that we could deal with at the same time. The first was the lack of symmetry in the method names. The words “provides” and “display” doesn’t reflect their close relationship and if you throw in the fact that they’re actually both related to rendering, it’s gets even more muddy.

And then he describes the Rails 3 version of the same functionality. Instead of provides/display it becomes respond_to/respond_with. In particular display @users becomes respond_with @users.

It’s only a tiny thing. Logically and functionally, they are exactly the same. But DHH’s version has an emphasis on the words that are used. How they couple together (display/provide versus respond_to/respond_with).

And there is the reason that I was uneasy about Rails 3. What if Rails lost this emphasis on the human factors – how the words mesh together – in the search of performance. Merb is written functionally, Rails is written emotionally – Merb is about performance, Rails is about feelings.

But DHH has made me feel much better about Rails 3 – he has shown that he will take Merb constructs and Railsify them, humanise them. Because, although code is executed by computers, it is written, and more importantly, read by people like me.

If you find this useful then please take a look at some of my other writing – or recommend me on Working with Rails. Cheers.

Writing tests for your controllers improves the design of your models

Saturday, December 20th, 2008

I’ve recently been updating some old code – partly written by someone else, partly written by myself. At the time, I thought I had written this code really well; looking back on it now, it looks awful. Fair enough, I’ve learnt a lot – I want to look back on old code and shudder. But also, there is very poor test coverage on this app and the tests that there are are quite unwieldy due to an over-reliance on fixtures.

So I’ve been reworking them all using RSpec, my fork of RSpec-Rails and my Object Factory (which means I can avoid fixtures).

Most of the work involves writing a spec that mimics the current behaviour (by inspecting the code and trying to match all paths through it), then refactoring the code, using the spec to prove that I haven’t broken it.

But some points have some really horrible code (and lots of it) within the controllers. As you probably know, Skinny Controllers is the Rails way – your application logic belongs in your models (as they are your application) – the controller should just find or create the relevant model, ask it to do something and then render the results.

Because of this, I opted to just rewrite the actions in question.

To do this I started by writing a Cucumber feature describing things from the user’s point of view. Actually writing the steps that match the feature was a lot of work; because Cucumber is a full stack test you have to deal with all the dependencies that your individual action has (for example, are you logged in with the correct permissions with all associated objects created and in the right state?).

Then I wrote a controller spec. Controller specs in RSpec should use mock objects; you don’t really want to test the models, you just want to prove that the controller finds or creates the right model, asks it to do something and renders the correct output at the end.

So a typical spec looks something like this (note that this is not RESTful as it was an existing part of the application that I am about to change):


  it "should process an item" do
    @item = mock_model Item, :work_type => :buy_stuff, :quantity => 2
    
    on_getting :process_item, :id => '1' do
     Item.should_receive(:find).with('1').and_return(@item)
      @stuff = mock_model Stuff
      @item.should_receive(:process).and_return(@stuff)
    end
    
    assigns[:stuff].should == @stuff
    response.should be_success
    response.should render_template('admin/orders/process_item')
  end

This basically says:

  • We have an item, of type “buy stuff” with a quantity
  • When the process_item action is called, we expect that the controller will try to find the item with the given id
  • Then we should call process on the item and it should give us some stuff
  • The stuff should be stored in an instance variable, called stuff
  • And a page should be successfully rendered using the process_item template

That’s a pretty succinct explanation of what the controller should do – I can’t think of many ways of making that skinnier. It also bears no resemblance to the actual implementation of the action – which currently looks something like this:


def process_work_item
    @item =Item.find(params[:id])
    case @item.product.class.to_s.underscore.to_sym
    when :buy_stuff
      @stuff = Stuff.build_item(@item)
      @stuff.setup_new
      render :action => :process_stuff
    when :update_stuff
      @item.stuff.prepare_for_update
      render :action => :update_stuff
    else
      render :status => 404, :text => "Item product type #{@item.product.class.to_s} unknown."
    end
rescue ActiveRecord::RecordNotFound
  render_not_found
end

Pretty complicated – and as new types of item are added we need to add more and more clauses to that case statement.

First things first – I’ve said that we should call “process” on the item class. So I add a pending spec to the Item specification – this is to remind me that I’ve got some work to implement later on.


  it "should process itself based upon its work type"

Then I rework the controller so that the controller spec passes.


    @item =Item.find(params[:id])
    @stuff = @item.process
    render :template => "admin/orders/process_item"

Pretty simple huh?

What we have done is shifted the logic from the controller into this new “process” method on the Item. We have made it so that the controller knows virtually nothing about the item – all it knows is how to find it and that it has a process method. All the implementation details are now hidden within the Item, out of the way of the outside world.

Through the use of mocking we can ignore actual implementations and concentrate on presenting ourselves as simply, and minimally, as possible to the outside world. This reduces coupling, increases flexibility and makes our code easier to read. Don’t you agree?