Back in March 2005 Kevin Lawrence wrote this great article for Better Software called "Grow Your Test Harness Naturally"
He's got a link to the PDF on his blog, luckily.
It's one of those articles that keeps being cited by various people one runs into here and there. I read it over and over until I Got It.
The basic premise is: don't write the framework first. Write some tests, then extract the common code from those tests, write more tests, abstract common code, write more tests, refactor, repeat. The refactoring generates the framework.
The thing is, I had never had enough code complex enough, running against an app stable enough, to really and truly build a framework this way.
I have a large number things to do with Watir.
First I automated each path through the code individually. I did about 10 of these.
Each of my paths had to set up a certain set of rules, so I abstracted a method "make_rules"
Each of my paths had to set some data before doing a final click, so I abstracted a method for that.
At this point my 1o individual scripts had shrunk to about 5 lines of code anyway, so I put them all in one file.
But I still have to handle various variations in the path through the code, so I wrote a controller.rb file that orchestrates all of the making of rules, the data handling and final clicking.
Now I'm adding new paths through the GUI. Adding each new path means rejiggering my existing libraries to accomodate the new path. But since my libraries were generated as a consequence of actual code, they're naturally in tune with what I want to do. Updating them to handle the first new path through the code takes some thought, but the next 10 times I need to go down that path all of the methods are already in place, and the repetition becomes trivial.
The framework is reliably going through the GUI about 80 times now, every time subtly different than every other time.
The thing is, I don't think I could have *designed* this framework. For one thing, I didn't have enough information when I started writing to anticipate all of the paths I would need. For another, even though my framework isn't very complex, it's still large enough that I doubt that I could have held the whole architecture in my head in order to write it in advance.
I can't believe how a) robust and b) readable this framework is turning out to be. I still have some mistakes to clean up, and I have a couple more paths through the code to add, but I'm so pleased to finally find out for myself that Kevin Lawrence is still right.