On Saturday, June 8, 2002, at 07:12 pm, chromatic wrote:
> On Saturday 08 June 2002 11:02, Michael G Schwern wrote:
[snip]
>> In reality, if Bar.pm changes in an incompatible way Foo.pm's own tests
>> should fail and that should cover you.
>
> Not in a strict isolation testing environment, where I don't want to
> use the
> real Bar.pm when testing Foo.pm.
>
> Maybe I'm being too strict about my isolation, but it's had good
> results for
> me so far.
[This message has became a bit of a ramble... apologies in advance :-) ]
I played with something a bit like the proposed Test::Depend, but I
abandoned it after a while since it didn't help me in the way I had
expected. Don't know if this will help the discussion but what I did was
roughly as follows...
- Have all of my mock objects stick their class, the method names
they were
called with, and $0 into a database. So you have a bunch of rows like:
MockFoo open Bar/t/bar.t
MockFoo close Bar/t/bar.t
....
- Manually maintain a mapping from MockFoo to the real class hierarchy
that implemented Foo (this could probably have been automated if I
could
have been bothered to think about it :-)
- Have a test for each module that compared an MD5 hash of each
method in the module (got by extracting 'sub method_name { .... }'
string from the .pm)
to the hash from the last run, and throw out some warnings on the tests
that used the mocked version of the same method if it had changed (or
vanished).
My hope was that this would help me in refactoring code. I wouldn't have
to keep track of what modules use what methods, so I could be more
confidant in making changes.
This fell down in three ways. Two minor, one major.
#1: Minor problem - Didn't work for AUTOLOAD methods, generated
methods,
etc.
#2: Minor problem - False negatives when changes were not in
method_name,
but something other private method of Foo that method_name called.
These were not really issues for me, probably because of my personal
coding style, so I didn't get a lot of false negative/positives.
Test::Depend will cope better with these problems since it looks at the
test results of the module as a whole. This should give an excellent
indication of semantic change (at the expense of it being module, rather
than method, specific).
Test::Depend also involves less work in implementing the unit tests
since you don't have to mess with the mocks.
However, it doesn't help with:
#3: Major problem - You have to check the warnings manually!
I found that, once you have a moderately complex system, it's hard to
determine whether changes you are being warned about are going to be an
issue (beyond simple things like method renaming). I spent too much time
looking at the code, and usually ended up writing a functional test to
make sure that I wasn't missing something.
I eventually just bit the bullet and started writing more functional
tests. This (of course) had the usual affect of writing more tests ---
it made development faster.
Worry about making a non-compatible change to a class? Not me. I just do
% make test >& functional1.txt
make the change, then repeat
% make test >&! functional2.txt ; diff functional1.txt functional2.txt
until the only difference I see is the time the tests took.
While this involves some repetition of the unit tests it does help track
things like changing APIs. If you change Foo in some non-compatible way
you get the following little pattern:
- Tests show that Bar's functional tests fail, but unit tests succeed.
- Update MockFoo so that Bar's unit tests fail the same way
- Fix Bar.pm so that all tests pass.
I don't run the functional tests as often as the unit tests so I don't
lose a lot of speed. It doesn't involve a lot of duplicate code since I
keep most of my tests in classes that allow me to swap mock/live objects
by subclassing and/or configuration options.
Once I started writing decent functional tests, my hack to track changed
methods suddenly ceased being useful. I think you may find the same
thing occurring with Test::Depend - it will just encourage you to write
more functional tests ;-)
Cheers,
Adrian
--
Adrian Howard <[EMAIL PROTECTED]>
phone: 01929 550720 fax: 0870 131 3033 www.quietstars.com