Unit testing in Rails: How To???
RoR Testing February 12th, 2008Steps in unit testing:
Unit test are mainly used to test the models in Rails.
Generally, there is one test for each model.
Unit testing involves testing the databases and the business rules in the model.
Default test Stub are created when you run script/generate model
Division of a unit test:
· GENERATION OF A TEST DATABASE
· WRITING THE UNIT TEST CASES INCLUDING ASSERTIONS.
· LOADING THE .YML FILE WITH DEFAULT VALUES
· RUNNING THE TEST CASE.
Writing the unit test case involves the following steps:
The first steps in the unit test case involves creation of the test database for the testing purpose which can be generated from the following command:
rake clone_structure_to_test or rake db:test:clone_structure
All the test cases for the models are written under the /test/unit directory.
The test class is the is the subclass of the Test::Unit::TestCase base class which tells the rails to generate the tests based on the Test::Unit framework.
Assertions can be used to test the necessary checkpoints within the test case.
Assertions are triggers which validate or test the current state of a webapp during the runtime.
After the preparation of the test case, we load the test database with some default data using fixtures.
Fixtures are available under the test/fixtures directory under the webapp.
We edit the .yml file to match the records in the test database and load the records with some default data.
To run the test we use the following command:
rubytest/unit/.rb
Checking The Code Coverage Of The Test:Using RCOV
Rcov takes the .rb files as the input and checks the code coverage of the test on the model file and generates the code coverage statistics as a html files and stores it in the folder named coverage in your webapp.
Optimizations then need to done on the .rb file until it shows a code coverage of almost 95-100%
Assertions:
The following is the list of assertions that can be used while writing the unit test cases:
Note:The [msg] is an optional string message you can specify to make your test failure messages clearer. It’s not required.
*assert* ( boolean, [msg] ) … ensures the object/expression is true
*assert_equal* ( obj1, obj2, [msg] ) … ensures obj1 obj2 is true @*assert_not_equal* ( obj1, obj2, [msg] )@ … ensures obj1 obj2 is false
*assert_same* ( obj1, obj2, [msg] ) … ensures obj1.equal?(obj2) is true
*assert_not_same* ( obj1, obj2, [msg] ) … ensures obj1.equal?(obj2) is false
*assert_nil* ( obj, [msg] ) … ensures obj.nil? is true
*assert_not_nil* ( obj, [msg] ) … ensures obj.nil? is false
*assert_match* ( regexp, string, [msg] ) … ensures a string matches the regular expression
*assert_no_match* ( regexp, string, [msg] ) … ensures a string doesn’t matches the regular expression
*assert_in_delta* ( expecting, actual, delta, [msg] ) … ensures the numbers expecting and actual are within delta of each other
*assert_throws* ( symbol, [msg] ){ block } … ensures a block throws the symbol
*assert_raises* ( exceptions ){ block } … ensures a block raises one of the comma-separated exceptions
*assert_nothing_raised* ( exceptions ){ block } … a block doesn’t raise one of the comma-separated exceptions
*assert_instance_of* ( class, obj, [msg] ) … ensures obj is the class type
*assert_kind_of* ( class, obj, [msg] ) … ensures obj is or descends from class
*assert_respond_to* ( obj, symbol, [msg] ) … ensures obj has a method called symbol
*assert_operator* ( obj1, operator, obj2, [msg] ) … ensures obj1.operator(obj2) is true
*assert_send* ( array, [msg] ) … ensures that executing the method listed in array[ 1 ] on the object in array[ 0 ] with the parameters of array[ 2 and up ] is true. This one is weird eh?
*flunk* ( [msg] ) … ensures the failure of the test
Here is a Demo example:
Example :Person Test: /test/unit/person_test.rb
require File.dirname(__FILE__) + ‘/../test_helper’
fixtures :person
class PersonTest < Test::Unit::TestCase
def setup
@people = Person.new
end
def test_something
#Write your test cases along with the necessary assertions here.
assert true, “Test implementation missing”
end
end
#example of the password test case.
def test_passwords
jimmy = Person.new
jimmy.first_name = ‘Jimmy’
jimmy.last_name = ‘McJimmy’
jimmy.password = ‘h1st0r3ct@my’
#The assertion lineup
assert !jimmy.password.empty?
assert jimmy.password.length > 5
assert_match /(0-9)/, jimmy.password
assert_not_equal ‘password’, jimmy.password.downcase
end









April 6th, 2008 at 1:55 pm
Hell yeah! This post sounds really good. Reading your blog is useful and interesting. Keep it that way.