Show Me The Money-8.2 - Round 2 with fitnesse

Now lets get our acceptance tests to pass too. It’s time for ScrawnyBalboa vs Fitnesse Round2! Let’s open up the wiki and see what we made the last time. We need to update the path directive since we changed the project folder when we downgraded the rails version. We don’t need the date coz that would auto-set to be the creation date

!define COMMAND_PATTERN {ruby -I %p "L:/ruby_home/lib/ruby/gems/1.8/gems/fit-1.1/bin/FitServer.rb" -v}
!path "L:/Gishu/Ruby/Rails/ShowMeTheMoney"

# Lucky Charm : Sample Test Fixture to check if Ruby FitServer is reachable
!|eg.ArithmeticFixture|
|x|y|+|-|*|/|
|1|1|2|0|1|1|

!|fit.ActionFixture|
|start|AcceptanceTests.EnterInflowRecords|
|enter|inflow|PayDay|5000|
|check|currentBalance|5000|
|enter|inflow|Interest|1000|
|check|currentBalance|6000|
|enter|inflow|PayDay|5000|
|check|currentBalance|11000|
Ok so let’s run this. The table looks self-explanatory. We are adding three credit entries and verifying the balance. Now that reminds us we didn’t implement the currentBalance tracking part! Make a note of that Ok so let’s write the Fit fixture code.

file: ShowMeTheMoneu\AcceptanceTests\enter_inflow_records.rb

module AcceptanceTests
class EnterInflowRecords < Fit::Fixture
def inflow dateCreated, sDescription, fAmount
end
def inflow= inflowObject
end
def current_balance
return 0
end
end
end
Now click on test in the wiki. It says inflow= method is called but missing. Strange. I add some trace lines to figure out what is going on. Turns out the inflow= method is being called with only the description param. It looks to me that that there can only be a max of three columns ever in an action fixture table. Let’s modify our test table like this
!|fit.ActionFixture|
|start|AcceptanceTests.EnterInflowRecords|
|enter|description|PayDay|
|enter|amount|5000|

|press|addEntry|

|check|currentBalance|5000|

|enter|description|Interest|

|enter|amount|1000.50|

|press|addEntry|

|check|currentBalance|6000.50|

|enter|description|PayDay|

|enter|amount|5000|
|press|addEntry|

|check|currentBalance|11000.50|
So now lets get that fixture working ..
require File.dirname(__FILE__) + '/../test/test_helper'
require 'inflow_controller'
require 'fit/fixture'

class RailsHelper < Test::Unit::TestCase
def setup
@controller = InflowController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
def test_dummy
end
end
module AcceptanceTests
class EnterInflowRecords < Fit::Fixture

attr_accessor :description, :amount
def initialize
@helper = RailsHelper.new("test_dummy")
@helper.setup
end
def addEntry
@helper.get :new
@helper.post :create, :credit => {:description => @description, :amount => @amount}
end
def current_balance
return Credit.count
end
end
end


Whoa! Lot of code there.
  • Since Rails has spoilt me.. I resorted to sneaky ways to glue my application code to the Fit table. The get and post methods are added to the Test::Unit::TestCase by Rails. Since our fixture has to inherit from Fit::Fixture, I turned to composition.. created a dummy test case derivation as a member of the fixture. Distilled out the essential things.. and it works!
  • Also current_balance as of now returns number of records in Credit table so that we know if the deal is going through (not what it should be doing but we will get to that).
Click Test to see it fail. And fail it does.
We’re seeing that record count is 2 + expected. We have 2 records in our fixture. Is that it ? A trace says Yes. So we stick in a Credit.delete_all in the test helper setup and we’re good! Now lets go after the current_balance implementation. We don’t have a controller page for it. For now let’s do the simplest thing that works… keep it in Credit itself as a class method. This test took me sometime.. I used assert_equal initially, then made a detour into coercing both arguments to same value and finally reached : ‘Remember when comparing 2 float values, use assert_in_delta’. Now it looks simple

file: \ShowMeTheMoney\test\unit\credit_test.rb

DELTA = 0.001 #tolerance  
def test_currentBalance
assert_in_delta totalAmountOfAllCreditEntries, Credit.currentBalance, DELTA, "Imbalance"
test_create
assert_in_delta totalAmountOfAllCreditEntries, Credit.currentBalance, DELTA, "Imbalance"
end

def totalAmountOfAllCreditEntries
obResultModels = Credit.find_by_sql("select sum(amount) as totalAmount from credits")
obResultModels[0].attributes["totalAmount"].to_f
end

file: \ShowMeTheMoney\app\models\credit.rb

def Credit.currentBalance
fCurrentBalance = 0
Credit.find(:all).each{|entry| fCurrentBalance += entry.amount}
fCurrentBalance
end


Ok now let’s get that acceptance test to pass. We correct current_balance method in enter_inflow_records.rb

def current_balance
Credit.currentBalance
end


And just like that Balboa lands one. Our first passing acceptance test!!

Next we can go on to implement the RowFixture table. But before that we need to incorporate deletes also into the above table. Hmm we need to spend more time thinking about our acceptance tests. We add some more steps to the above table to simulate the user choosing to delete the last record (hey everyone makes mistakes) and verifying that the current balance is still correct.

!|fit.ActionFixture|
|start|AcceptanceTests.EnterInflowRecords|

|check|currentBalance|11000.50|

|enter|select_entry|3|

|press|delete|

|check|currentBalance|6000.50|

We add some more steps to the above table to simulate the user choosing to delete the last record (hey everyone makes mistakes) and verifying that the current balance is still correct. We update the fixture code to deal with the new steps.

This gave me a bit of a fight.
  1. I initially used selectEntry as the table method to mark a record for deletion. Creating accessor :select_entry => undefined method ‘selectEntry’. Creating an accessor :selectEntry didn’t work => fit server wasn’t able to find select_entry=. In the end I just settled with select_entry in the html table.
  2. I initially implemented delete as shown below. This didn’t work – the record was not deleted.
    def delete
@helper.post :destroy, :id => @select_entry.to_i
end


Little spying around lead to ‘Record#1 doesn’t mean id#1’ Well that just skipped my mind. However that’s a good thing coz we now have another test that we missed – trying to delete a record via manually editing the url. Make a note. I add the Record# to Record id lookup and..

    def delete
@helper.post :destroy, :id => getID_ForSelectedEntry
end
def getID_ForSelectedEntry
obSelectedEntry = Credit.find(:all, :order => "id")[@select_entry.to_i - 1]
obSelectedEntry.id
end
Ta da!









No comments:

Post a Comment