Our solution has been to force rSpec to load everything in app/models and app/controllers before the specs are run. We do this in the rspec_helper, and since this is loaded multiple times (on different paths) it's also useful to restrict this code so it only runs once.
First, here's the code that loads the models and controllers:
class ForceLoader
def self.run
["models", "controllers"].each do | app_component |
directory = File.join(RAILS_ROOT, "app/") + app_component
Dir[directory + "/**/*.rb"].each { |file| require_dependency file }
end
end
end
There are two things to note about this code:
- we use require_dependency for consistency with other Rails loading, rather than require or load;
- we need to ensure that the path of the file passed to require_dependency is the same as the path used by default by Rails. Ruby loading is path passed, and if you refer to the same file with two different path representations you may load it twice.
Next, let's look at the code that we put in rspec_helper.
begin
ForceLoader
rescue
require File.dirname(__FILE__) + '/force_loader'
ForceLoader.run
end
If we can't reference ForceLoader we load it and run it. Once the class is loaded the rescue code won't be invoked, so this ensures once only execution.
Hopefully this approach will give you more accurate coverage reports with minimal overhead - it's certainly uncovered at least one problem on our project so far. It can also be extended to cover other parts of your app in a fairly straightforward way.
No comments:
Post a Comment