At the Forge - Testing Rails Applications with Shoulda

New to testing? Just want an easier time with Test::Unit? Shoulda is the answer.

The past few months, I've been looking at a number of tools that make it easier for Ruby on Rails developers to improve the reliability of their software using automated testing. Even if you don't fully subscribe to the notion of test-driven development (TDD) or its cousin, behavior-driven development (BDD), the fact that Rails makes it so easy to test each part of your code makes it less likely that foolish mistakes will creep into your applications.

By default, Rails comes with Test::Unit, a test suite that makes it possible, and even easy, to check your code. Coupled with the test classes that come with actionpage, one of the core Ruby gems that comes with Rails, you can create a comprehensive test suite at the unit (model), functional (controller) and integration (cross-controller) levels. If you have a comprehensive test suite, you easily will detect, and understand the implications of, changes you make to the code that break the test.

That said, Test::Unit sometimes can be a bit verbose and repetitive. If you are writing unit tests, and you want to make sure that a particular attribute has been tested completely, it would be nice to be able to express a number of test cases quickly and tersely. Tests can function, in many ways, as a type of specification (as I will explain when we get to RSpec and Cucumber in coming months), and the easier it is to read these specifications, the less likely odd behavior is to slip through the cracks. It also goes without saying that the easier it is to write tests, and particularly comprehensive tests, the more likely you are to write them.

This is why Shoulda, a set of macros that work with Test::Unit, has become popular among Ruby developers in general and Rails developers in particular. Shoulda, developed by Tammer Saleh, a programmer who works for the Thoughtbot consulting company in Boston, is a set of macros that makes it easier to write tests with Test::Unit, as well as easier to read them. I have begun to use Shoulda with projects that I test with Test::Unit and have found it to be quite enjoyable.

This month, I take a look at Shoulda, and how you can integrate its macros into the tests you write in a Rails application. I explain how Shoulda divides tests into contexts, allowing you to group tests together even within a single file. I also describe how Shoulda's various macros make it easy to run a number of tests using a single readable line.

I should note that although Shoulda originally was designed to be used with Test::Unit and to provide something of an RSpec-like environment for Test::Unit users, it adds a growing amount of support for RSpec as well. Even if you use RSpec, you might want to consider using Shoulda along with your standard RSpec tests (or specs). I haven't looked at the combination for my own work, but it might be appropriate for what you're doing.

Installation and Basic Use

Shoulda comes packaged as a Ruby gem, and can be installed as:

sudo gem install thoughtbot-shoulda --source=http://gems.github.com

Earlier versions of Shoulda came packaged under a slightly different name (Shoulda, rather than thoughtbot-shoulda). It also is possible to install Shoulda as a Rails plugin; in this article, I assume that you have installed the gem version.

You can incorporate the gem in your configuration file, config/environment.rb:

config.gem "thoughtbot-shoulda", :lib => "shoulda", 
 ↪:source => "http://gems.github.com"

With that in place, your Rails application either will run with Shoulda in place, or it will fail to load, complaining that the gem has not been installed. In one of my favorite Rails functions, you then can type:

rake gems:install

and your Rails application will examine its list of required gems, download those that are not yet on the system and install them in the appropriate places.

Let's assume you have created a simple Rails application that contains a single model that describes people. You can create it in the following way:

rails simple
cd simple
./script/generate model Person firstname:text lastname:text
 ↪birthdate:date grade_in_school:integer phone_number:text 
 ↪email_address:text
rake db:migrate

At this point, you now have a simple Rails application (using the built-in default database, SQLite) with a single model defined. By creating your model with a generator, you get the following simple unit test file:


require 'test_helper'

class PersonTest < ActiveSupport::TestCase
  # Replace this with your real tests.
  test "the truth" do
    assert true
  end
end

True, you can invoke rake test on this, and the tests will succeed, but that's because the test is completely empty. You can write:

rake test:units

______________________

Webcast
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers

Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.

Learn More

Sponsored by AMD

White Paper
Red Hat White Paper: Using an Open Source Framework to Catch the Bad Guy

Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6

Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.

Learn more about catching the bad guy in this free white paper.

Learn More

Sponsored by DLT Solutions