Introduction
In our previous tutorials we have gotten a good headstart
in terms of development. Now we will look at the second
aspect of our Rails application, testing. Rails beautifully
tucks in the unit testing inside the framework. It generates
the skeleton code when models and controllers are generated.
Rails tests offer one very big benefit over regular tests,
they can emulate browser requests and hence, we don't need a
browser to test our application's response to the
requests.
Setting Up the Test Environment
As Rails applications have a lot of database interaction,
it is advised to write tests that check for the constancy of
data insertion and retrieval. In order to do so we need to
setup a test database and populate it with dummy application
data. In this way we can test our application without the
data in development and production.
Our database configuration file,
database.yml contains a section called test,
where we define the name of the test database and connection
details. This is how our database.yml file
looks:
test:
adapter: mysql
database: eim_test
username: root
password: rails
host: localhost
In order to populate the test database we write fixtures.
Fixtures reside in the test folder of application
directory.

Click here for larger image
Figure 1
The tests are of four types : Unit, Functional,
Integration and Performance.
So let's create our test database and populate it with
the test data. First go to MySQL Query browser and create an
empty database with the name eim_test.
Go to
app_directory/test/fitxtures/employees.yml to
edit the users fixtures file. Fixture is a YML file with the
name as the name of the table. We need to define the data in
a format that corresponds to the columns of the table.
Name Of the Fixture:
Column Name: Value
saurabh:
name: Saurabh
designation: cto
address: mumbai
Now, run the command:
C:eim> rake db:migrate RAILS_ENV="test"
C:eim> rake db:fixtures:load RAILS_ENV="test"

Click here for larger image
Figure 2

Click here for larger image
Figure 3
Now, we are ready to write unit tests into our
application because our test environment is ready.
Unit Test for Our Models
When we created our model or scaffold, a default test is
created with it. The employee_test.rb under
test/unit looks like this by default
require 'test_helper'
class EmployeeTest < ActiveSupport::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end
What it does is take a class, it creates an instance of
it, and passes the value inside that instance. It then
compares it with the values of it inside the database. So,
now we test our employee model as follows:
require File.dirname(__FILE__) + '/../test_helper'
class EmployeeTest < ActiveSupport::TestCase
def test_initialize
first_employee = Employee.new(:name => 'Sam', :designation => 'ceo',:address => 'california')
assert_equal('Sam',first_employee.name)
assert_equal('ceo',first_employee.designation)
assert_equal('california',first_employee.address)
end
end
We initialize our unit test, create an an instance of the
class employee called first employee and pass values inside
it. Assert equal, method goes and check the database
whether the values have been inserted correctly or not.
Once we have written our assertions, we simply go and run
the test file just like we do any Ruby program.
C:eimtestunit> ruby employee_test.rb

Click here for larger image
Figure 4
The dot (.) just above Finished line in the screenshot
indicates the test has passed.
In order to test the validations inside the model, we can
write a simple test method , which creates an instance of
the model class and tries to insert null data. If the test
passes, it means the validation is running fine and no data
has been insterted.
def test_should_not_save_employee_without_name
employee = Employee.new
assert !employee.save
end
Now the above methods of testing write particular
functionality and define how the data should be passed using
that. This method is commonly used for what is known as Test
Driven Development or TDD. In TDD , first the tests are
written with conditions that fail. Then the code is written
and tests are made to pass. It is a commonly followed
approach. There are however new approaches that have come up
in last few years like Behavior Driven Development, which we
will look in our later tutorials.
Functional Tests For Controllers
The tests for model, check the insertion and retrieval of
the data using our model classes. The controller tests check
for the flow of the actions. Which actions? Success of the
user request, authentication, redirection, display of
messages correctly.
These tests lie inside tests/functional folder. While
writing the scaffold we had generated the skeleton tests.
Here is how our default index test looks.
class EmployeesControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:employees)
end
Test should get index means the test should go to the
index action and make a get request, and makes
sure that request gets fulfilled and checks whether a valid
post method has been added to the instance
variable.
We will customize our tests now.
test "should create employee" do
assert_difference('Employee.count') do
post :create, :employee => {:name => 'John',:designation => 'officer',:address => 'california' }
end
assert_redirected_to employee_path(assigns(:employee))
end
In this test, the test case, first checks for the number
of records, then using the create action, sends a post
request, with the data inside the instance. Once that is
done, it sends the request to redirect it to the appropriate
page after the action has been performed.
We can also make use of the fixtures we created earlier
in order to perform these tests. Then we can simply call the
fixture as an attribute inside the instance and it will pass
all the values defined in the fixture automatically. Earlier
in this tutorial we created a fixture called saurabh, we
will use that fixture to test our show, edit methods.
test "should show employee" do
get :show, :id => employees(:saurabh).to_param
assert_response :success
end
test "should get edit" do
get :edit, :id => employees(:saurabh).to_param
assert_response :success
end
The types of requests handled by these tests are get,
post, put, head, delete, which are http requests in general.
Apart from the requests, once the request has been
fulfilled, hash objects will be generated and they would be
available at the disposal of the tests to use.
- Assigns - They are objects assigned for use
inside the views and contain instance variables.
- Cookies - Any available cookies for the
application
- Flash - Any Flash objects, which means Flash
method to display messages inside rails.
- Session - All the stuff that lives inside session
variables.
Conclusion
We have looked at how we can check the application flow
and the data insertion inside our rails application. We have
seen how are tests work and written some basic tests. There
are however several kinds of assertions available in the
Rails testing framework, which can be checked on the Rails
API.
In the coming tutorial we will look at testing the views,
integration tests, and the basics of Behavior Driven
Development.
Original Story