Make it so with RSpec Macros

RSpec macros (like those in the fantastic Remarkable library) ease spec writing for repetitive tasks, but is that process more effort than it’s worth? No — it’s actually quite easy to write and include macros for your specs to do some of the standard heavy lifting.

This is a great resource to get started with how to write the actual macros (or custom matchers) themselves.

What tripped me up was how to actually include them in my examples. Monkeypatching is rarely a clean process. And, while the comments on that post mentioned a public API, how to use that API wasn’t immediately obvious (as with many things about RSpec).

In my case, I was looking to define a quick login! macro that would allow me to easily create a before block to log in as a specified user or just as a FactoryGirl generated one in a TwitterAuth based app. Here’s the module I wrote and stuck in my spec_helper.rb:

module LoginMacro   def login!(user=Factory(:user))     before do       @current_user = user       controller.stub!(:current_user).and_return(@current_user)       session[:user_id] = @current_user.id     end   end end

So that was relatively straightforward and now what I wanted to be able to do was call it in my controller specs like this:

describe UsersController do   describe "#create" do     login!          it 'should etc. etc.'   end end

As it turns out, RSpec offers the ability to add macros and matchers via the config.extend and config.include methods on the RSpec configuration object (extend is for class-level macros like the one I wrote here, include is for instance-level matchers). You just have to add this to your spec helper’s configuration portion:

config.extend(LoginMacro)

Voila! Now your specs will be able to use the login! macro to set up a user in no time.

Experienced RSpec users are already familiar with this, but I find that certain things can be hard to come across if you don’t already know how to use them. So I thought I’d blog for the benefit of others like me: this is an easy way to use RSpec macros.