Customizing Rake:spec


For Quottly, we have a lot of code in our rails app. Most of it is a regular web application, but we also have a significant amount of code that is used for importing data from different data providers.

We write tests for our data import code, like all our code. But the tests for that part of the code are pretty slow. We use a lot of machine learning code, and training classifiers is time intensive.

When we’re working on the web app, we want to be able to run our specs quickly. What to do?

We decided to make rake:spec just run our web app specs, ignoring our import specs. And we created a new task, rake spec:import, that runs the import specs.

How to do this?

First, a gotcha: you can’t just override a rake task definition. If you want to re-define a rake task, you have to call Rake::Task["task_name"].clear before re-defining it.

Second, how do we redefine rake:spec? This isn’t quite straightforward - the documentation for customizing the rspec rake task isn’t great.

This will do, in one of our rake task files:

3 do |t|
  t.rspec_opts = '--tag ~type:import'

Instead of instantiating our new spec using the standard rake task definition, we use rspec’s custom rake task. Then, we just pass an option - the equivalent of passing command line options. The ~type declaration indicates that we’ll exclude the passed type, so --tag ~type:import indicates that we’ll exclude all specs tagged with type: import.

Now we just need a new rake spec:import task. To do this, just copy the above, but change :spec, to :import, and remove the tilde.

Finally, we need to make sure all our import specs are labeled with type: import, and wrap our task definitions in unless Rails.env.production?. Since rspec isn’t loaded in production, it’ll throw an error if we try to define these tasks in production.

This should get you going. Don’t forget to add rake spec:import to the appropriate spots (e.g. in your CI build configuration) where you should be running all your specs.

Happy hacking!

Get Notified of New Posts

* indicates required