Copyright © tutorialspoint.com

Ruby on Rails 2.1 - Applications' Unit Testing

previous next

Advertisements

Introduction:

Before proceeding let's have a quick look of few definitions:

Rails Testing:

When you run the helper script script/generate to create controllers and models, Rails generate a framework for unit and functional tests. You can get pretty good test coverage by filling in the framework with tests for the functionality you write. There are two important points to test in a Rails application:

This tutorial will cover both the testings in brief. So let's create one testapp to understand the concept.

C:\ruby> rails -d mysql testapp

Database Setup:

Till now we have used only Rails application's development database, but now you needed to make sure that the testing database is also created and appropriate section of your config/database.yml file was set up correctly.

Let's create development and testing databases as follows:

mysql> create database testapp_test;
Query OK, 1 row affected (0.01 sec)

mysql> create database testapp_development;
Query OK, 1 row affected (0.01 sec)

mysql> use testapp_test;
Database changed

mysql> grant all privileges on testapp_test.* 
          to 'root'@'localhost' identified by 'password';
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

Configuring database.yml:

Configure your config/database.yml as follows:

development:
  adapter: mysql
  encoding: utf8
  database: testapp_development
  username: root
  password: password
  host: localhost
test:
  adapter: mysql
  encoding: utf8
  database: testapp_test
  username: root
  password: password
  host: localhost
production:
  adapter: mysql
  encoding: utf8
  database: testapp_production
  username: root
  password: password
  host: localhost

Generate Migration:

Assume you have a table containing books, including their titles, price and a small description. The following migration sets up this table:

testapp > ruby script/generate migration books

Now modify the testapp/db/migrate/20080616170315_books.rb file as follows:

class Books < ActiveRecord::Migration
  def self.up
     create_table :books do |t|
        t.string     :title, :limit => 32, :null => false
        t.float      :price
        t.text       :description
        t.timestamp  :created_at
     end
  end
  def self.down
    drop_table :books
  end
end

Now run the migration as follows:

testapp > rake db:migrate

This will create books table in testapp_development database. Now after this we need to set up your test database using rake command as follows:

C:\ruby\testapp > rake db:test:clone_structure

This will clone testapp_development database into testapp_test database. It means whatever you have in development database, now you will have in test database as well.

Testing Models:

When you generate a model with the generate script, Rails also generates a unit test script for the model in the test directory. It also creates a fixture, a YAML file containing test data to be loaded into the testapp_test database. This is the data against which your unit tests will run:

testapp > ruby script/generate model Book
      exists  app/models/
      exists  test/unit/
      exists  test/fixtures/
      create  app/models/book.rb
      create  test/unit/book_test.rb
      create  test/fixtures/books.yml
      create  db/migrate
      create  db/migrate/20080616164236_create_books.rb

As you write code in the model classes, you'll write corresponding tests in these files. So let's create two test book records using YAML in test/fixtures/books.yml as follows:

perl_cb:
  id: 1
  title: 'Ruby Tutorial'
  price: 102.00
  description : 'This is a nice Ruby tutorial'
java_cb:
  id: 2
  title: 'Java Programming'
  price: 62.00
  description : 'Java Programming for the beginners'

Now let's relace exsiting code in book unit test file test/unit/book_test.rb with the following code:

require File.dirname(__FILE__) + '/../test_helper'

class BookTest < ActiveSupport::TestCase
  fixtures :books

  def test_book

    perl_book = Book.new :title => books(:perl_cb).title, 
                         :price => books(:perl_cb).price,
                         :description => books(:perl_cb).description,
                         :created_at => books(:perl_cb).created_at

    assert perl_book.save

    perl_book_copy = Book.find(perl_book.id)

    assert_equal perl_book.title, perl_book_copy.title

    perl_book.title = "Ruby Tutorial"

    assert perl_book.save
    assert perl_book.destroy
  end

end

Finally, run the test method as follows:

testapp > ruby test/unit/book_test.rb

Here's the output of running the successful test case:

testapp > ruby test/unit/book_test_crud.rb 
Loaded suite ./test/unit/book_test
Started
.
Finished in 0.0625 seconds.

1 tests, 4 assertions, 0 failures, 0 errors

What has happend here:

This is how we can test our Rails Models.

Testing Controllers:

Controller testing is also known as functional testing. Functional testing tests the following type of functionalities of the controllers:

Rails framework supports 5 types of requests and to write a functional test, you need to simulate any of the five HTTP request types that your controller will process. :

Request type "get" and "post" are the most commonly used in controller testing. All these methods take four arguments:

In this tutorial, we will see how to use get method to test our controller. You can test rest of the methods in similar way.

When you generate a controller with generate, Rails creates a functional test script for the controller as follows:

testapp > ruby script/generate controller Book
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/book
      exists  test/functional/
      create  app/controllers/book_controller.rb
      create  test/functional/book_controller_test.rb
      create  app/helpers/book_helper.rb

As you write code in the controller classes, you'll write corresponding tests in these files. Before that let's define our controller functions list, show, and search inside app/controllers/book_controller.rb as follows:

class BookController < ApplicationController
  def list
    @book_pages, @books = paginate :books, :per_page => 10
  end

  def show
    @book = Book.find(params[:id])
  end

  def search
    @book = Book.find_by_title(params[:title])
    if @book
      redirect_to :action => 'show', :id => @book.id
    else    
      flash[:error] = 'No such book available'
      redirect_to :action => 'list'
    end
  end
end

NOTE: You would need two views templates for show and list method. You can define those views and test them, but right we will proceed without defining those views.

Now let's reuse our test fixture which is in test/fixtures/books.yml file as follows:

perl_cb:
  id: 1
  title: 'Ruby Tutorial'
  price: 102.00
  description : 'This is a nice Ruby tutorial'
java_cb:
  id: 2
  title: 'Java Programming'
  price: 62.00
  description : 'Java Programming for the beginners'

Add the following test_search_book and test_search_not_found methods to test/functional/book_controller_test.rb to test the functionality of the Book Controller's search action.

require File.dirname(__FILE__) + '/../test_helper'
require 'book_controller'

# Re-raise errors caught by the controller.
class BookController
   def rescue_action(e) 
      raise e 
   end
end

class BookControllerTest < Test::Unit::TestCase
  fixtures :books
  def setup
    @controller = BookController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
  end

  def test_search_book
    get :search, :title => 'Ruby Tutorial'
    assert_not_nil assigns(:book)
    assert_equal books(:perl_cb).title, assigns(:book).title
    assert_valid assigns(:book)
    assert_redirected_to :action => 'show'
  end

 def test_search_not_found
    get :search, :title => 'HTML Tutorial'
    assert_redirected_to :action => 'list'
    assert_equal 'No such book available', flash[:error]
  end
end

Now run your test cases as follows:

testapp > ruby test/functional/book_controller_test.rb 

This gives following output:

Loaded suite test/functional/book_controller_test
Started
..
Finished in 0.422 seconds.

2 tests, 7 assertions, 0 failures, 0 errors

Let's see what has happened here:

For a complete detail on Assertions ,please refere to Rails Standard Documentation.

Using Rake for testing:

You can use rake utility to test your applications. Here are few important commands.


previous next

Copyright © tutorialspoint.com