noizZze

Readability Aliases to RSpec Let-objects

RSpec has many great features that makes the spec’ing life easier, and one of them is the objects letting. Here’s what it is briefly:

1
2
3
4
5
6
7
describe Album do
  let(:album_with_image) { Factory(:album) }

  it "should have cover image" do
    album_with_image.cover_image.should_not be_nil
  end
end

As you can see, you are just defining the name of the object and how it can be initialized. Later in the tests you use it as a local variable and it’s always the same object inside each test. One positive side is that you can define as many objects as you need for your tests, but they will actually be initialized when and if you need them.

Now imagine this picture:

1
2
3
4
5
6
7
8
describe ActivityLogger do
  let(:post) { Factory(:post) }

  it "should log creation of a post" do
    post # creating new post
    Log.should ....
  end
end

Here we need to access “post” for RSpec to create an instance for us. That’s not very readable, right? I basically want it to look:

1
2
3
4
it "should log creation of a post" do
  create_post
  ...
end

Here’s how I do it without hard-coding the methods for all possible factories that I may want to define (from “/spec/support/helpers.rb”):

1
2
3
4
5
6
7
def method_missing(name, *args)
  if /^created?_(.+)$/ =~ name.to_s
    send $1
  else
    super
  end
end

Now I can address “post” as “create_post” and “created_post”. Of course, it creates a “create*” and “created*” aliases for every method in the scope, but I don’t worry about that since the naming is very specific.

Love it, hate it?