RAILS UNIT TEST MODEL

Ruby on Rails 3 Testing

Artifacts for Testing Under test

  • Sub-directories Description

    • fixtures Contain testing data
    • functional Testing for individual controllers
    • integration Integration test for multiple controller
    • test_helper.rb Testing configuration unit Unit testing for models
    • Ruby on Rails Test Fixtures
  • Before running tests, Rails load the testing DB data with a pre-defined data called test fixtures

For unit and functional test, by default, load all data under texts/fixtures:

Remove any data from the DB table corresponding to the fixture Load the fixture data into the table Load the fixture data into a variable Test fixtures (accounts.yml)

account1:
  user_name: John Smith
  description: My user 1 description
  premium: false
  income: 100000
  ranking: 1.5
  fee: 9.99
  birthday: 2000-02-21
  login_time: 2011-02-21 18:07:36

account2:
  user_name: Tom Jones
  description: My user 2 description
  premium: false
  income: 80000
  ranking: 2.3
  fee: 9.99
  birthday: 1990-05-21
  login_time: 2011-02-21 18:07:36

Each fixture starts with a name followed by indented key/value pairs Data is separated by a blank space in the first column comment out the whole line Adding Ruby code in text fixture

<% base_income = 100000 %>
account1:
  income: <%= base_income * 0.9 %>
  login_time: <%= 10.days.ago.to_s(:db) %>

account2:
  income: <%= base_income * 0.85 %>
  login_time: <%= 15.days.ago.to_s(:db) %>

Accessing Test Fixture Data Access from a predefined variable


accounts(:account1)
accounts(:account1).income
Access from the DB

accounts(:account1).find

Create 1-to-Many Association Test Fixture Objects

Order composes of 1-to-many items

orders.yml

order1:
  order_name: book purchase

order2:
  order_name: cloth purchase
items.yml

o1_item1:
  item_name: ruby book
  order: order1

o1_item2:
  item_name: rails book
  order: order1

o2_item1:
  item_name: jeans
  order: order2

Create Many-to-many Association Test Fixture Objects

Vendors have many clients (or vice versa)

vendors.yml

sev:
  vendor_name: SEV enterprise

sco:
  vendor_name: SCO enterprise
clients.yml with the assocaition

uix:
  client_name: UIX LCC
  vendors: sco, sev

coco:
  client_name: Coco LCC
  vendors: sco

Ruby on Rails Unit Test

Edit

test/unit/vendor_test.rb

require 'test_helper'

class VendorTest < ActiveSupport::TestCase

   # Use fixtures data vendors and clients
   fixtures :vendors, :clients

   test "check data is valid" do

     vendor = Vendor.new

     # Assert not valid since vendor_name is required
     assert !vendor.valid?

     vendor.vendor_name = "E1"
     assert vendor.valid?

     # Compare value
     assert_equal vendor.vendor_name, "E1"

   end

   test "check associations" do
     # Retrieve data from the fixture
     sco = vendors(:sco)

     # Assert SCO should have 2 clients
     assert (sco.clients.length == 2)
   end

   test "check assoication data" do
     sco = vendors(:sco)
     uix = clients(:uix)

     # Get vendors of uix
     companies = uix.vendors

     # Check if sco is one of the vendors
     assert (companies.include? sco)

     coco = clients(:coco)

     # Assert coco vendors is sco
     assert_equal coco.vendors, [sco]

   end

end
  • Rails Assert Function Description
    • assert false Assert based on a boolean value
    • assert_not_nil assigns Assert controller has set the value of the named variable
    • assert_response :success for http 200, :redirect for 300-399, :missing for 404, :error for 500-599
    • assert_redirected_to Assert where the request redirect to
    • assert_difference Assert the row counts changed by n (Default 1)
    • assert_equal obj1, obj2 obj1 == obj2
    • assert_not_equal obj1, obj2 obj1 != obj2
    • assert_same obj1, obj2 obj1.equal?(obj2)
    • assert_not_same obj1, obj2 not obj1.equal?(obj2)
    • assert_nil obj obj.nil?
    • assert_not_nil obj not obj.nil?
    • assert_match regexp, string Match a regular expression
    • assert_no_match regexp, string Not match a regular expression
    • assert_in_delta expecting, actual, delta Actual is within the delta range of expected
    • assert_throws :SomeError {…} Expect SomeError is thrown
    • assert_raise ex1, ex2, … {…} Expect one of the exception is thrown
    • assert_nothing_raised ex1, ex2, … { …} Expect none of the exception in the list is thrown
    • assert_instance_of class, obj obj is an instance of class
    • assert_kind_of class, obj obj is kind of class
    • assert_respond_to obj, :some_method obj implement some_method
    • assert_operator obj1, operator, obj2 obj1.operator(obj2)
    • assert_valid record The model object is valid
    • assert_difference expressions, difference {…} The change of value in expression before and after the code block
    • assert_no_difference expressions {} Assert no different in the expression before and after the code block
    • assert_send array Execute a method flunk Fail a test
    • assert_recognizes Asserts that the routing of the given path is correct – Testing the Rails routing data
    • assert_generates Asserts that the generated path is correct – Testing the Rails routing data
    • assert_template Asserts that the request was handled by the right template file The assert methods above an optional “message”
    • assert false, "Failed"

Run the Unit test

Prepare the DB schema

rake db:migrate

Recreate the testing environment DB with db/schema.rb

rake db:test:load
For sub-sequent testing

rake db:test:prepare

Check for available migrations and warn the user Load the test schema Testing rake task

Rake Tasks Description

rake db:test:purge // Empty the test database
rake db:test:clone	// Recreate the test
database from current environment
rake db:test:clone_structure	// Recreate the test databases from the development environment
  • Run individual test or method
cd ctest
ruby unit/account_test.rb

ruby unit/account_test.rb -n test_register
  • Run all unit tests
rake test:units

If test “check assoication data” fails, the following message will be displayed