I’m writing a script to process a directory structure and some files
within it. The process depth-first searches the directory tree from
some root and looks for a Manifest file. When it finds it, it
processes the file (XML plist, containing keys for filenames and
paths) and records some information about the files referenced in the
manifest. This recorded information then gets posted to a web service
Actually, I already wrote this using my usual top-down style. First,
I wrote the code to depth-first search the directories. This included
code to test all entries in a directory (using #file? and
#directory?). Next I wrote the code to detect the manifest file. Then
I used the plist gem to read it into memory (great gem). Then I wrote
the code to do my magic on the files referenced in the plist. Etc.
I just iterated through my requirements until I had a finished product.
When I finished I decided to write tests to verify each method.
However, the main entry point into the script starts off by doing the
directory traversal which then feeds into every other step. I can’t
call the method without running all of its dependent methods (which
essentially runs the whole program). This strikes me as my first clue
that I probably did this wrong.
So now I’d like to rewrite it using TDD.
I need some advice from the TDD experts out there.
Is it fair to say that I should rewrite bottom-up? That is, start
with methods that are independent of others. For example, assume no
subdirs and just get a list of entries from the current directory.
Then write the method to iterate those entries. Then write one to
test if the entry is a file or a directory. Etc.
Do you generally keep all methods in a class independent of each
other? How do you write, and then test, methods that have
dependencies on each other (and therefore cause side effects)?
How does one mock or stub out a SOAP call? What’s the difference
between a stub and a mock?
How do you test a method that utilizes an instance variable that
was set somewhere else? E.g. #methodA calculates @result. #methodB
retrieves @second_result. #methodC compares @result and @second_result.
Instead of treating these as global to the class instance, should I
be passing them as method parameters?
I appreciate any and all insight. I’m hoping to continually improve
as a programmer so I can answer these questions instead of always