In a recent series of articles, you learned how to set up a proof of concept for an online bookstore created using Ruby-on-Rails. In this four-part article series, you'll start creating the application for real, using test-driven development. This article is excerpted from chapter two of the book Practical Rails Projects, written by Eldon Alameda (Apress; ISBN: 1590597818).
Author Management for an Online Bookstore - Testing in Rails (Page 2 of 4 )
As of version 1.1, Ruby on Rails has three different testing schemes built in: unit testing, functional testing, and integration testing. All of the Rails tests use (either directly or indirectly) the Test::UnitRuby library.
InTest::Unit, tests are built on the notion of assertions. Assertions are methods that test the output of their arguments. The mother of all assertions methods,assert, for example, tests that its argumentís code returnstrue. If the return value of the assertion argument isfalseornil, the assertion has failed, and the failure will be reported.
Unit testing is used in Rails to test business logic objects, represented by ActiveRecord models. (ActiveRecord is the object-relational mapping system in Rails, and it is described in the next section in this chapter.) Common tests for ActiveRecord models check that, for example, all validations work as they should and that all the methods you have written yourself work as intended.
For example, the following code tests that the validation of a newPerson object does not pass unless the object has both the first and last name specified. It also checks that the methodPerson#agecalculates the age correctly from the date of birth of a person. For that, we use another useful assertion method,assert_equal, which makes sure that its two arguments are equal.
class PersonTest < Test::Unit::TestCase def test_validation p = Person.new(:first => 'George', :last => nil) assert !p.valid? p.last = 'Pork' assert p.valid? end
def test_age p = Person.create(:first => 'George', :last => 'Pork', :dob => (Date.today - 35.years)) assert_equal 35, p.age end end
Functional tests in Rails test single controllers and can be used to test that simple user stories work correctly. While unit tests in Rails focus on single ActiveRecord classes, functional tests focus on controller actions, which are called with the getandposthelpers, just as they would be called by real HTTP requests.
Functional tests have a bunch of Rails-specific assertions for testing the response that results from the action. We will use functional tests extensively later in this chapter to implement the author management functionality for the Emporium project.
Integration testing is a newcomer in Rails 1.1. Unlike functional tests, integration tests can span multiple controllers and be used to test Rails routing. Therefore, integration tests can be used to test complete user stories, ranging from signing in, to putting things into the shopping cart, to checking out. We will discuss integration testing in more detail in Chapter 3.
Tip Routing is a built-in system in Rails to map URLs to controllers and actions and vice versa. The default route in Rails is:controller/:action/:id, which means that, for example, the URLhttp:// localhost:3000/books/show/1would be routed to theBooksControllerís actionshow, and the action would be to receive anidparameter with a value of1. While the default routing is intuitive and easy to use, custom routing can be used to construct very flexible URL schemes.