So, yes, well. I was talking today with Chet about my little payroll demo of yesterday, and saying that if I were to go forward with more articles, I’d need acceptance testing. (Among other reasons, some of the interesting learnings about the project are found in the acceptance tests.) So we decided to try to set up Fitnesse to run on my Macbook Air.
I’ll not take you through the bloody details. Suffice to say that we got the server running quickly enough, but that nothing we tried would get Fitnesse to load my fixture. So there was an hour or ninety minutes that I’ll never get back.
I decided instead to use rspec, and to rewrite the handful of acceptance tests that we provide with the class. That turned out to be much easier, since I used for the web conversion that brought me to ronjeffries.com.
I began by moving the little payroll Ruby program to a separate folder hooked up to GitHub, so I can save versions as I go along. The existing unit tests ran immediately, just as one would hope. Then I set up a spec folder and put in my standard hookup test:
require 'rspec' describe 'hookup' do it "should return 4" do expect(2+2).to be(4) end end
That ran happily, which was a delightful change from the experience with Fitnesse.
As you’ll recall from last time, I had coded all my classes directly in the unit test fixture, an idea I stole from Keith Braithwaite’s “TDD as if you really mean it”. He would probably not go so far as to create actual classes in there, but I had taken that liberty. It was time to break out those classes into their own files.
So then I extended the hookup section to refer to Timecard, and to expect it in its own file:
require 'rspec' require_relative '../timecard' describe 'hookup' do it "should return 4" do expect(2+2).to be(4) end it 'should let me create a timecard' do timecard = Timecard.new(31) expect(timecard.regular_hours).to be(31) end end
I still consider this a hookup test: it’s just checking to see that I can access the Timecard class from a separate file. I moved the Timecard code into
timecard.rb, and this test ran as well. Life is good.
Carrying on that process, I quicly broke out the payroll program into separate class files for Employee and Payroll classes as well as Timecard. With the proper includes, not yet added, that should work fine. I view this as a refactoring, and I changed the unit test to reflect the breakout:
require 'test/unit' require_relative 'timecard' require_relative 'employee' require_relative 'payroll' class PayrollTest < Test::Unit::TestCase def test_base_pay regular_hours = 40 time_card = Timecard.new(regular_hours) base_rate = 10 employee = Employee.new(base_rate, time_card) payroll = Payroll.new(employee) base_pay = payroll.base_pay assert_equal(400, base_pay) end end
That tells me that the multi-file version is working. The acceptance test still works, since it only references the Timecard file. It’s not yet aware of the other files. That will show up in the real acceptance tests, to come.
The next step will be to create rspec acceptance tests matching our Story 1 Fitnesse tests, and make them run.
We’ll turn to that in a moment, probably in a separate article. A question one might ask here is whether I’ll continue to try to make Fitnesse work, and whether I’ll use it. The answers are “maybe”, and “no”.
“Maybe”, because maybe I’ll try to make it work, since I have had a kind offer from someone who has Fitnesse working on the Mac, and I’ll at least try his setup. I suspect, however, that it may want a 1.9ish Ruby and I’m running 2.0 at the moment and don’t plan to go back. So I might make Fitnesse work for completeness but not because I want to use it.
“No”, because my purpose with these articles will be to demonstrate a very incremental approach to growing the design, à la Adventures in C#. Fitnesse won’t help me much with that, and since I like rspec better, I’ll just stick with this if and when I write more of these articles.