Show Me The Money-6 - On Rails.. Toot! Toot!!

Iteration#1 : Day 6/10

The Story So Far: Alright, its been rough weather.
But now we got all that behind us and we can TDD our way to the end of the first story. Yup we’re on rails! Well I get the book again and rush thru Mike Clark's most excellent Chap12."Task T: Testing" for the nth time.

First we need to clone the structure from dev database to our test database. We can reuse the sql file (smart move!)
>mysql money_test <db\Create.sql -u gishu -p
We take Creation of credit enties first. MVC.. Model first.
Rails being helpful as always should have already created the test class file when we generated the scaffold.
CREATE
Well lets see if we can write a test to add a new credit entry.. Some chipping away here n there and we have..

file:
L:\gishu\ruby\Rails\ShowMeTheMoney\test\unit\credit_test.rb

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

class CreditTest < Test::Unit::TestCase
#fixtures :credits

def setup
Credit.delete_all
end
def test_create
obCreditEntry = Credit.new
obCreditEntry.description = 'Payday'
obCreditEntry.amount = 5000
assert obCreditEntry.save, obCreditEntry.errors.full_messages.join("; ")

assert_equal 1, Credit.count
obCreditEntry.reload

assert_not_nil obCreditEntry.id
assert_not_nil obCreditEntry.created_at
assert_equal 'Payday', obCreditEntry.description
assert_equal 5000, obCreditEntry.amount
end
end


  1. first I had to comment out the fixtures directive because we are not using it yet. And it was blowing up with some exception on a test run. (Later found out it was due to the default fixture file was incomplete)
  2. The setup method blows away all the records in our table.
  3. test_create first adds a record, reloads the record data and verifies the create operation. All set for a test run
L:\Gishu\Ruby\Rails\ShowMeTheMoney>ruby test\unit\credit_test.rb
Loaded suite test/unit/credit_test
Started
.
Finished in 0.157 seconds.

1 tests, 6 assertions, 0 failures, 0 errors
Hey! We did not have to do anything to make it pass. Rails made the code pass. Anyway we should refactor – value duplication in the test. Introduce local vars
sDescription = 'Payday'
fAmount = 5000

RETRIEVE
Lets write one to verify that we can retrieve multiple stored records. Although it is taken care of by the previous test.. lets write one to be sure.
This time we will use Rails fixtures i.e. YAML (text) files whose contents are loaded into the test database for snappy testing.
So let’s edit it (auto-created like most things in Rails). Make sure you don't use tabs and indent using spaces.

file:
L:\gishu\ruby\Rails\ShowMeTheMoney\test\fixtures\credits.yml
salary_credit_entry:
id: 1
created_at: 2008-01-19 00:00:00
description: salary
amount: 15000
interest_credit_entry:
id: 2
created_at: 2008-01-20 00:00:00
description: interest
amount: 1000.50

You uncomment the magic-drippin’ line, which blows away the test DB, adds the two new records and loads them up into instance variables for us to use
fixtures :credits
And write a new test case
def test_retrieve
obCredit = Credit.find(1)
assert_kind_of Credit, obCredit
assert_equal @salary_credit_entry.id, obCredit.id
assert_equal @salary_credit_entry.description, obCredit.description
assert_equal @salary_credit_entry.amount, obCredit.amount
assert_equal @salary_credit_entry.created_at, obCredit.created_at
end


And we need to comment out the existing setup and test_create methods temporarily – they need to be updated to work with the rails fixture. So lets run the test case
test_retrieve(CreditTest):
RuntimeError: Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
test/unit/credit_test.rb:33:in `test_retrieve'
Some console trace lines later, I find that the records are being added to the test DB but the @credits hash and @salary_credit_entry are nil. NO! That can't be... the book says otherwise.
I’m beginning to think this project is jinxed.. however a little sleuthing turns this Mike Clark’s
(most excellent again) post up … Change in Rails defaults (test_helper.rb) again!
Apparently they switched on transactional fixtures and removed auto-created instance variables to make the unit tests go faster.
We can (always configure and) turn them back on using
self.use_instantiated_fixtures = true
OR
Update our test cases like this (and I didn’t need the _before_type_cast tricks like the book says)
def test_retrieve
obCredit = Credit.find(1)
assert_kind_of Credit, obCredit
assert_equal credits(:salary_credit_entry).id, obCredit.id
assert_equal credits(:salary_credit_entry).description, obCredit.description
assert_equal credits(:salary_credit_entry).amount, obCredit.amount
assert_equal credits(:salary_credit_entry).created_at, obCredit.created_at
end

That passes. Now to get the first test to work with fixtures.. we don’t need the setup method and I update the expected record account to 1 + 2 fixture records. That's all - ALL GREEN!



































No comments:

Post a Comment