Re: Testing .. but not as I know it

2001-02-14 Thread Piers Cawley

Robin Szemeti <[EMAIL PROTECTED]> writes:

> On Tue, 13 Feb 2001, you wrote:
> 
> > > to wit, testing of object based modules. Firstly what do people generally
> > > use for this? Test::Unit ?? or is there something more freindly out
> > > there?
> > 
> > Test::Unit *almost* does the right thing, but looking through the code
> > there are some horrible things being done (by someone who doesn't seem
> > to understand the reflection/introspection and dynamic features of
> > Perl),
> 
> they didn't even understand 'use strict;' so I expect there are other
> gaps too
> 
> since it does *almost* the right thing and I *almost* know what I'm doing
> with it .. I'll hang with it then for now.
>
> > and the test suite it comes with doesn't seem to have
> > desperately good coverage of the various testing modules. Which is why
> > I'm working on it...
> 
> uh huh .. I noticed various bits of the Tk gui were a little err 'sub
> obtimal' :) ... 
> 
> lerrus know when you get it nailed down then.
> 
> > > secondly abstraction:
> > > 
> > > If I have , say a 'data' object 
> > 
> > Why does the data object have to know how/if it's stored? Have a data
> > librarian object which is responsible for handling moving objects into
> > and out of storage. Then test the librarian to make sure that it can
> > retrieve stuff in the appropriate fashion, and do your data object
> > unit testing (possibly) without even having the librarian loaded up.
> > If you *do* find that you need to have the librarian loaded for some
> > of the data object's methods to work, think hard and see if you can't
> > find some way of removing that dependency. 
> 
> uh huh ... sorta got that ... so basically anything with anything that
> looks like sql or a $dbh handle ends up in the Librarian .. the outer
> class has all the other stuff  I aint sure about the 'without even
> having the librarian loaded' bit .. surely you test the librarian and
> then test the outer class with the librarian loaded iff the librarian
> passes its tests? .. otherwise you end up having to write a dummy
> librarian class that has every chance of not correctly behaving as the
> real librarian .. or do you just run the librarian tests on the dummy
> class as well?/ ... I though the idea was to build from ground zero, and
> include tested base classes into higher order classes and then test them
> as you go along .. or is that not it? ... 

Okay, we're into 'ideal situations here', but here goes.

Consider a clothes catalogue, with, say, the following classes:

ProductLine (ie Levis 501s)

StockItem, inherits from ProductLine (ie Levis 501s, 32W 34L, stone
washed)

Then, to set up the objects we'd do something like:

  my $levis = 
  ProductLine->new(category_name => 'Levis 501s',
   description => '...',
   stock_item_attribs => [...]);

  $levis->new_stock_item(waist => 32, length => 34,
 finish => 'blue stonewashed',
 quantity => 100);

The new_stock item method would then create a stock item (possibly
with a weakref back to its parent productline, but that's dependent on
whether we're ever going to need to use that...), and one of the
product lines would have a list of stock items associated with it.

Then, we could write a method to find all the actual items in stock by
doing something like:

   sub ProductLine::items_in_stock {
   my $self = shift;
   grep {$_->quantity > 0} $self->stock_items;
   }

Which wouldn't have to deal with the database at all.

If the librarian does the Right Thing, then we could say to it:

   $librarian->store($levis) 

and it would go away and store not only the $levis ProductLine object,
but also its associated stock items. And, when we come to reload the
$levis productline then it will either reload all its stock items, or
will place 'proxy' objects in their place which will trigger the
reloading of the real object when required. (Doing it this way stops
the reload of a single item doing a 'six degrees of separation' trick
and pulling in the entire object web.)

At a higher level, we could stick all our product lines into some top
level Catalogue object and simply stash that in the database, but it may
be that we should actually conflate the Catalogue with the librarian
to make for more memory efficient searches for products.

The point of taking this approach is that, when we want to test
ProductLine and StockItem there is no need to worry about how they are
stored, we can simply write a bunch of code that sets up a bunch of
productlines and stockitems and test away in that environment. 

When we want to test the Catalogue, then of course we're going to need
a database standing by, but we can use a dummy, empty database, set up
a bunch of objects, store 'em and test that storage and reloading work
like they're supposed to.

Which is, admittedly, not the initial approach I mentioned to you in
private email, but I've thought about it 

Re: Testing .. but not as I know it

2001-02-13 Thread Robin Szemeti

On Tue, 13 Feb 2001, you wrote:

> > to wit, testing of object based modules. Firstly what do people generally
> > use for this? Test::Unit ?? or is there something more freindly out
> > there?
> 
> Test::Unit *almost* does the right thing, but looking through the code
> there are some horrible things being done (by someone who doesn't seem
> to understand the reflection/introspection and dynamic features of
> Perl),

they didn't even understand 'use strict;' so I expect there are other
gaps too

since it does *almost* the right thing and I *almost* know what I'm doing
with it .. I'll hang with it then for now.
   
> and the test suite it comes with doesn't seem to have
> desperately good coverage of the various testing modules. Which is why
> I'm working on it...

uh huh .. I noticed various bits of the Tk gui were a little err 'sub
obtimal' :) ... 

lerrus know when you get it nailed down then.

> > secondly abstraction:
> > 
> > If I have , say a 'data' object 
> 
> Why does the data object have to know how/if it's stored? Have a data
> librarian object which is responsible for handling moving objects into
> and out of storage. Then test the librarian to make sure that it can
> retrieve stuff in the appropriate fashion, and do your data object
> unit testing (possibly) without even having the librarian loaded up.
> If you *do* find that you need to have the librarian loaded for some
> of the data object's methods to work, think hard and see if you can't
> find some way of removing that dependency. 

uh huh ... sorta got that ... so basically anything with anything that
looks like sql or a $dbh handle ends up in the Librarian .. the outer
class has all the other stuff  I aint sure about the 'without even
having the librarian loaded' bit .. surely you test the librarian and
then test the outer class with the librarian loaded iff the librarian
passes its tests? .. otherwise you end up having to write a dummy
librarian class that has every chance of not correctly behaving as the
real librarian .. or do you just run the librarian tests on the dummy
class as well?/ ... I though the idea was to build from ground zero, and
include tested base classes into higher order classes and then test them
as you go along .. or is that not it? ... 

> The difference between a Unit test and an Acceptance test is that the
> unit test tries its damndest to test the behaviour of the class and
> its methods etc independently of everything else in the system.
> An Acceptance test then tests that the entire system behaves as it
> should for a given task.

oh right .. thats a bit clearer ... so what do you do when a class works
with its dummy stubs but fails when a sub-class is plugged in instead? in
the latter model that would not get picked up until the acceptance test
... and then it might be difficult to see exactly where it went worng... 

hmm the trick seems to be not so much in the semantics of perl (the whole
OO thing of method dispatch and inheritance is fairly straightforward
really now I get to grips with it ) its mainly down to the design and
subtlties of which bits go in where ... 

ho hum .. back to the codeface.

-- 
Robin Szemeti

The box said "requires windows 95 or better"
So I installed Linux!



Re: Testing .. but not as I know it

2001-02-13 Thread Piers Cawley

Robin Szemeti <[EMAIL PROTECTED]> writes:

> Rightio ...
> 
> since its a Tuesday and also a waning 3/4 moon its *New Methodology Day*
> and the random choice from Big Ted's bookcase was XP::Installed
> 
> to wit, testing of object based modules. Firstly what do people generally
> use for this? Test::Unit ?? or is there something more freindly out
> there?

Test::Unit *almost* does the right thing, but looking through the code
there are some horrible things being done (by someone who doesn't seem
to understand the reflection/introspection and dynamic features of
Perl), and the test suite it comes with doesn't seem to have
desperately good coverage of the various testing modules. Which is why
I'm working on it...

> secondly abstraction:
> 
> If I have , say a 'data' object that can store, retreive and list various
> data in a schema, good OO practice would suggest that I test the object
> without knowing whether it stores its data in a flatfile, a databse or
> DNA structure, what is important is that it can store, retreive and list
> the info ... but obviously I have to tell it to use (in this case) a test
> MySQL db to load and retreive info from .. which seems contradictory ..
> or is that the difference between unit tests and acceptance tests ...
> unit tests are allowed to test specific variants of modules (flatfile
> based, MySQL based etc) where as the acceptance tests just work with
> whatever module is loaded and treat it as a black box ...???
> 
> am I making any sense ? .. oh well ...

Why does the data object have to know how/if it's stored? Have a data
librarian object which is responsible for handling moving objects into
and out of storage. Then test the librarian to make sure that it can
retrieve stuff in the appropriate fashion, and do your data object
unit testing (possibly) without even having the librarian loaded up.
If you *do* find that you need to have the librarian loaded for some
of the data object's methods to work, think hard and see if you can't
find some way of removing that dependency. 

The difference between a Unit test and an Acceptance test is that the
unit test tries its damndest to test the behaviour of the class and
its methods etc independently of everything else in the system.
An Acceptance test then tests that the entire system behaves as it
should for a given task.

-- 
Piers




Testing .. but not as I know it

2001-02-13 Thread Robin Szemeti

Rightio ...

since its a Tuesday and also a waning 3/4 moon its *New Methodology Day*
and the random choice from Big Ted's bookcase was XP::Installed

to wit, testing of object based modules. Firstly what do people generally
use for this? Test::Unit ?? or is there something more freindly out
there?

secondly abstraction:

If I have , say a 'data' object that can store, retreive and list various
data in a schema, good OO practice would suggest that I test the object
without knowing whether it stores its data in a flatfile, a databse or
DNA structure, what is important is that it can store, retreive and list
the info ... but obviously I have to tell it to use (in this case) a test
MySQL db to load and retreive info from .. which seems contradictory ..
or is that the difference between unit tests and acceptance tests ...
unit tests are allowed to test specific variants of modules (flatfile
based, MySQL based etc) where as the acceptance tests just work with
whatever module is loaded and treat it as a black box ...???

am I making any sense ? .. oh well ...

-- 
Robin Szemeti

The box said "requires windows 95 or better"
So I installed Linux!