---
title: Document Explicit Dependencies Through Tests
teaser: |
  Split your `spec_helper.rb` file into a
  minimal `spec_helper.rb` file and a `rails_helper.rb` file
  to load only the necessary dependencies in a spec.
  This is now the default in Rails.
tags: web,rails,testing
author: Greg Lazarev
published_on: 2014-05-06
---

One of the purposes of writing tests is to
[provide living documentation of application's code][living documentation].
Tests provide real examples of how a certain class or function is supposed to be
used. Tests could also document the exact dependencies of the tested code.

## The Problem

When Rails boots it loads most, if not all, of the application's code, along
with all of the dependencies (gems). Because of this, there is no need to
require dependencies in individual files that contain application logic. When
looking at the source of a specific class, it is hard to tell what external code
it depends on. The test doesn't help either.

A typical RSpec test usually looks something like this:

```ruby
require 'spec_helper'

describe StyleGuide do
  # actual tests omitted
end
```

In the Rails community, it has become a de facto standard to require the default
`spec_helper` (or an equivalent) in each test file. A typical
`spec/spec_helper.rb` file ends up loading the whole Rails environment,
requiring numerous helper files, and setting up various configuration options.
All of that, en masse, is more than what any particular test file needs.

Certainly, integration and feature tests depend on the entire Rails environment.
ActiveRecord model tests depend on the presence and configuration of a database.
These are all good use cases for `spec_helper`. But what about unit tests that
don't require the database? When testing a plain old Ruby class, there might
only be a few dependencies, if any.

## The Solution: RSpec 3.x `rails_helper.rb` and `spec_helper.rb`

RSpec 3.x introduces a new [`rails_helper.rb` convention][relish]
which contains all the Rails-specific spec configuration and leaves
`spec_helper.rb` minimal, with no Rails code.

[relish]: https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#default-helper-files

Here's an example `rails_helper.rb`:

```ruby
ENV["RAILS_ENV"] = "test"

require File.expand_path("../../config/environment", __FILE__)

require "rspec/rails"
require "shoulda/matchers"

Dir[Rails.root.join("spec/support/**/*.rb")].each { |file| require file }

module Features
  # Extend this module in spec/support/features/*.rb
  include Formulaic::Dsl
end

RSpec.configure do |config|
  config.include Features, type: :feature
  config.infer_base_class_for_anonymous_controllers = false
  config.infer_spec_type_from_file_location!
  config.use_transactional_fixtures = false
end

ActiveRecord::Migration.maintain_test_schema!
Capybara.javascript_driver = :webkit
```

Here's an example `spec_helper.rb`:

```ruby
require "webmock/rspec"

RSpec.configure do |config|
  config.expect_with :rspec do |expectations|
    expectations.syntax = :expect
  end

  config.mock_with :rspec do |mocks|
    mocks.syntax = :expect
  end

  config.order = :random
end

WebMock.disable_net_connect!(allow_localhost: true)
```

## Using the minimal `spec_helper.rb`

Being conscious about what must be required for a particular source file is a
good thing. Instead of loading everything but the kitchen sink,
let's specify the minimum dependencies inside of the test.

Here's a revision of our code from above:

```ruby
require 'rubocop'
require 'app/models/style_guide'

describe StyleGuide do
  # actual tests omitted
end
```

This code states exactly what the tested class (`app/models/style_guide.rb`)
depends on: the gem `rubocop` and the model `style_guide`.

Note that we don't need to require `spec_helper` manually in
either `rails_helper` or in our `StyleGuide` spec.
It is required for us in `.rspec` by default:

    --color
    --warnings
    --require spec_helper

The idea behind `spec_helper` is to keep it minimal and
resist the urge to add things to it.
It should avoid becoming a junk drawer.

Tests which might be part of a Rails application test suite, but don't actually
depend on Rails or ActiveRecord can now require this basic spec helper along
with the essential gems and files.

Each test now explicitly documents dependencies of the tested code.
Loading minimal dependencies during tests removes any magical coupling,
helps with refactoring,
saves time during debugging,
and makes tests run faster.

## What's next

Want to learn more techniques about decoupling code away from Rails?

* [Fast Rails Tests](https://www.youtube.com/watch?v=bNn6M2vqxHE)
* [Decoupling from Rails](https://www.youtube.com/watch?v=tg5RFeSfBM4)
* [Fast Tests With and Without Rails](https://www.destroyallsoftware.com/screencasts/catalog/fast-tests-with-and-without-rails)
* [Refactoring Out Helper Object](http://railscasts.com/episodes/101-refactoring-out-helper-object)
* [7 Patterns to Refactor Fat ActiveRecord Models](http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/)

[living documentation]: http://en.wikipedia.org/wiki/Unit_testing#Documentation
[Hound]: https://github.com/thoughtbot/hound
