Super Spread Sheet S³

Or little computing tricks and hacks

Testing with RSpec in Rails, Part 1, Introduction

Testing in Rails is both hard and easy. Hard because it takes as much time as coding does, but easy because there are many tools that make the most complicated things straightforward. There are so many tools though, that sometimes it is hard to choose. Neat paradox.

When setting up testing for my app, I did not find in one place a comprehensive explanation of the Rails testing process as a whole. This is an attempt to fix the situation.

Why testing?

The issue is more what and when to test. Michael Hartl has an introduction to testing in his Ruby on Rails tutorial, which describes why testing and the kinds of tests he is likely to do. In summary,

  • first test the controllers and the models, in other words unit testing;
  • second test the functionality across models, views and controllers, the integration tests;
  • and third, the views, but if they are likely to change, they can be skipped.

He also mentions the importance of writing regression tests on bugs found and having tests in place before any refactoring.

RSpec testing infrastructure

Set up

When a new Rails project is created with default settings, a test directory is created, coupled to work with minitest. From the word GO, I started using RSpec (http://rspec.info/, since I used the Ruby on Rails tutorial mentioned above which used RSpec as testing framework. I believed it has changed since.

I did not want that default directory, as I wanted the RSpec set up.

By issuing the command

rails g controller StaticPages about --no-test-framework

the test files related to the StaticPages controller will not be created. To create the right files, RSpec must be installed. That is done by including its gem in the Gemfile. RSpec takes advantage of a series of helpers to run tests automatically. The gems are specified following:

group :development, :test do
  gem 'rspec-rails'
  gem 'factory_girl_rails'
end

group :test do
  gem 'selenium-webdriver', '2.35.1'
  gem 'faker'
  gem 'capybara', '>= 2.2.0'
  gem 'guard-rspec'
  gem 'launchy'
end

and then run bundle.

In my opinion, the most interesting about Rails testing, is the interaction with databases and RSpec plus helpers makes this easy.

By default, every Rails application has three environments: development, test, and production. The database for each one of them is configured in config/database.yml.

http://guides.rubyonrails.org/testing.html

That fact is simply brilliant, as the development database is NOT the same as the test database. One can create automatically hundreds of records to test for specific features in isolation.

To run any testing, the databases need to be created, so run

rake db:create:all

which will create the databases which do not exist and inform you of the ones already created. The information on the databases description is taken from the file config/database.yml, which should include the information about test, development and production databases. Make sure that the three are name differently!

Then run

rails generate rspec:install

which generates the following configuration files:

.rspec
spec/spec_helper.rb
spec/rails_helper.rb

All tests and helpers will reside in the spec directory. This is directory where RSpec searches for the tests to run.

NOTE: After making changes to any of the models in development, you have to migrate the changes to the test database as well by running

rake db:migrate RAILS_ENV=test

With this, the testing infrastructure is set up.

Syntax

RSpec uses mainly the words “describe” and “it” so we can express concepts like a conversation:

“Describe an order.”
“It sums the prices of its line items.”

The describe method creates an ExampleGroup. Within the block passed to describe you can declare examples using the it method. Under the hood, an example group is a class in which the block passed to describe is evaluated.

The broad syntax of the test is as follows:

describe Object do
  it "Descriptive message of the test" do
    code with expectations
  end
end

Each “it” line only expects one example. Best practice is to test one thing at a time to make it simple to find errors. Although the descriptive message is technically optional, omitting defeat the purpose of individual testing. Previous RSpec examples had the “should” beginning the message, however that just clutters the output. A direct verb suffices.

Actual testing

Now to writing the tests. But where to start? With how to run a test.

To run a test, use the command

rspec

from the root directory of the app. If used alone, it will run all the tests found in the spec directory. You can also specify a directory or a filename including its path with respect to root. RSpec will run all tests found in that directory in the first case, or just the file specified in the second.

The testing framework automatically creates directories to sort out the tests. My spec directory looks like this:

controllers/  factories/       models/         requests/       support/
helpers/      rails_helper.rb  spec_helper.rb  views/

Next is what to test: unit testing, integrations testing, views, regression testing.

Unit testing: Models

Models are the building blocks of the application. They are also easier to test since their behaviour should be well defined in any application. I considered them to be first priority to test.

Everyday Rails

The blog Everyday Rails considers the following to be essential model tests:

  • the factory should generate a valid object
  • data validation
  • class and instance method

Full text deployed in a post called Testing with RSpec in Rails, Part 2, Models.

Unit testing: Controllers

Post in development.

Integration tests

Post in conception.
This should test the functionality across models, views and controllers.

View’s tests?

Will I create a post?
Code in the views tend to change often, so there are different schools of thought on whether to test or not.

Regression tests

Automatic test runs with Guard

Guard runs the test suite upon the detection of a modification of file in the spec directory or as specified in the Guardfile. It also sets the testing environment just once, speeding up the running of subsequent tests. To set up (gem already included in the Gemfile) run:

bundle exec guard init

which creates the Guardfile describing how and when Guard is to run. In his tutorial, Guard: Michael Hartl’s Rails tutorial, he explains the set up in more detail, although using minitest instead of RSpec.

To start guard just type in a terminal

$ guard

It will create a shell and guard will start listening to any changes in the spec directory or any other file specified in the Guardfile. The Guarfile created in the set up is a very good starting point.

Type enter in the shell to run all the tests in the spec directory. Ctl-D to exit.

(Explanation on Guard needs expansion.)

Advertisements

2 responses to “Testing with RSpec in Rails, Part 1, Introduction

  1. Pingback: Testing with RSpec in Rails, Part 2, Models | Super Spread Sheet S³

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: