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:
1 2 3 |
|
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!