Configuring Code Coverage for Ruby/Rails project
Getting Started
SimpleCov is a code coverage analytical tool for Ruby 1.9 built as ruby gem.
In order to use it in your project add this gems to your Gemfile:
group :coverage do
gem 'simplecov', :require => false
end
The formatter for SimpleCov is packaged as a separate gem called simplecov-html. You don’t have to include it explicitly - SimpleCov already has it as a dependency.
You don’t have to call coverage as separate command. Instead, you have to integrate it with your specs or tests. How to do it?
You have to start SimpleCov before any of your specs/tests in order to be covered:
# spec_helper.rb
if ENV['COVERAGE'] == 'true'
require 'simplecov'
SimpleCov.start
end
# my_model_spec.rb
require 'spec_helper'
describe MyModel do
...
end
Now you can run your specs:
rspec spec/my_model_spec.rb
Coverage report will be saved in coverage folder. Open up coverage/index.html in your browser and check out results:
open coverage/index.html
If you want to save results to another folder, change coverage_path property:
SimpleCov.coverage_path = 'my_output'
In real project you have different groups of specs executed by separate commands. If you want to merge coverage results generated by each of command into total report, you have to assign unique command name for each group of specs:
# model_spec_helper.rb
if ENV['COVERAGE'] == 'true'
require 'simplecov'
SimpleCov.command_name "rspec:models"
SimpleCov.start unless SimpleCov.running
end
# domains_spec_helper.rb
if ENV['COVERAGE'] == 'true'
require 'simplecov'
SimpleCov.command_name "rspec:domains"
SimpleCov.start unless SimpleCov.running
end
SimpleCov Adapters
SimpleCov understands notion of adapter. You can start SimpleCov with preconfigured rails adapter:
SimpleCov.start 'rails'
Let’s look closer at definition of rails adapter:
SimpleCov.adapters.define 'rails' do
...
add_filter '/config/'
add_filter '/db/'
add_filter '/vendor/bundle/'
add_group 'Controllers', 'app/controllers'
add_group 'Models', 'app/models'
add_group 'Mailers', 'app/mailers'
add_group 'Helpers', 'app/helpers'
add_group 'Libraries', 'lib'
add_group 'Plugins', 'vendor/plugins'
end
As you can see, adapter definition includes filters and groups. Filters specify which directories and files will be includes into coverage. Groups define separate tabs of coverage report.
You can read more about groups and filters on SimpleCov home page.
If you are not satisfied with rails adapter, you can create your own:
def register_adapter adapter_name
SimpleCov.adapters.define adapter_name do
add_filter '/spec/'
add_filter '/db/'
add_filter 'lib/tasks/'
add_filter '/vendor/'
add_filter '/config/'
add_group "Domain", "app/domain"
add_group "Models", "app/models"
add_group "Services", "app/services"
end
end
Full Example
Let’s create compete example that can be used in any project:
# spec_helper.rb
def init_spec command_name
...
SimplecovHelper.run_simplecov command_name,
"your_adapter_name" if ENV['COVERAGE'] == 'true'
...
end
And this is SimpleCov helper implemented as utility module:
module SimplecovHelper
extend self
def run_simplecov command_name, adapter_name
require 'simplecov'
SimpleCov.command_name command_name
start_simplecov(adapter_name) unless SimpleCov.running
end
private
def start_simplecov adapter_name
register_adapter adapter_name
SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
SimpleCov.at_exit do
SimpleCov.result.format!
end
SimpleCov.start adapter_name
end
def register_adapter adapter_name
...
# see implementation in previous section
end
end
Alternatives
Another gem dedicated to code coverage is coco gem.
It provides simple code coverage report and it’s much easier to configure, but resulting report is much simpler and less convenient.
You can choose what tool to use in your project based on your preferences.
If you need to cover your javascript code, you can visit my previous blog article.