Wednesday, December 5, 2012

Ruby on Rails - RSpec Tutorial

Hello,

It seems that there isn't a lot of RSpec tutorial that's clear out there.
Let's see if I can write one that's clear.

Assuming that you already have a Ruby on Rails app and are trying to add unit test to your app using RSpec:

  1. Add "gem 'rspec'" to your Gemfile
  2. Run ".../project$ bundle install"
  3. After the RSpec gem is installed, run ".../project$ rails generate rspec:install"
You will see that a "spec" folder is created inside your project folder:
project/
  app/
  config/
  Gemfile
  ...
  spec/

Inside the "spec" folder, you have a "spec_helper.rb" file.
That helper file makes sure that all necessary files under test are loaded.
It contains the following:

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'

# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
  # ## Mock Framework
  #
  # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
  #
  # config.mock_with :mocha
  # config.mock_with :flexmock
  # config.mock_with :rr

  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = true

  # If true, the base class of anonymous controllers will be inferred
  # automatically. This will be the default behavior in future versions of
  # rspec-rails.
  config.infer_base_class_for_anonymous_controllers = false

  # Run specs in random order to surface order dependencies. If you find an
  # order dependency and want to debug it, you can fix the order by providing
  # the seed, which is printed after each run.
  #     --seed 1234
  config.order = "random"
end

As you can see, the environment is set to "test." You can change it if you would like. 
Also, bolded lines in blue above are not commented out by default. If you do not use a relational DB (like me, I use MongoDB), feel free to comment them out.

Create the "controllers," "models," and "views" folders inside the "spec" folder:
spec/
  controllers/
  models/
  views/

Let's say you would like to create a test file for one of your controllers, posts_controller.rb, go into the "spec/controllers" folder, create a file called "posts_controller_spec.rb." Make sure that "_spec" is on the file name because that's how RSpec identifies its test files.
Assuming that you have an action called show within your posts_controller.rb, open up the "post_controller_spec.rb" and add the following:

#The spec_helper makes sure that we load all necessary files in.
require 'spec_helper'

#Test the PostsController
describe PostsController do
  #Test the show action
  describe 'show' do
    it "returns all posts" do
      get :show 
      response.should_not be_nil
    end
  end
end
      
Save the file.
Go out to your project directory and run ".../project$ rake spec"
The "rake spec" command is to run all unit tests within your "spec" folder.
To run the unit test in an individual file, execute ".../project$ rspec spec/controllers/posts_controller_spec.rb"

That's all there is to it. Hope I was being clear.
Please feel free to leave a comment if I am not.

No comments:

Post a Comment