[Zope-dev] Zope unit testing framework?
Tres Seaver
tseaver@palladion.com
Mon, 28 Feb 2000 18:16:31 -0600
Martijn Faassen wrote:
>
> Tres Seaver wrote:
>
> > I got addicted to unit testing after reading John Lakos' excellent book, _Large
> > Scale C++ Software Design_. He emphasises not only unit tests, but a more
> > elaborate strategy, "design for testability:" not only does each module come
> > with its own tests, but the system knows about dependencies between modules, and
> > guarantees to test the depended-on modules before their dependents (so as to
> > avoid spurious errors).
>
> In fact I also read that book a while back, and it was the first to set me
> on of good testing strategies. I don't think Lakos discusses tests that
> automatically check the outcome though, as the UnitTest frameworks are
> doing. The advantage there is that you don't have to hand-verify the
> test output, and that you can test often (so you'll see quickly when
> something goes wrong).
Umm, I'd have to go back and look, but I think he specifies automatic failure
detection, modeled on the "power on self test" of IC's. The way I did "design
for testing" with C++ was to create/capture desired output, put it under version
control, and then use the diff command line tool to automate, as part of a "make
test" target. New tests required appending new output. A typical module would
consist of four elements:
* Foo.h # interface
* Foo.cpp # implementation
* Foo.test.cpp # Test driver main()
* Foo.req # required output
The "make test" sub-target for Foo looks like (tested)::
test: Foo.pass
clean:
rm -f *.o *.test *.pass *.errors
Foo.o : Foo.h Foo.cpp
${CC} -c Foo.cpp
Foo.test.o : Foo.h Foo.test.cpp
${CC} -c Foo.test.cpp
Foo.test : Foo.o Foo.test.o
${CC} -o $@ Foo.o Foo.test.o -lstdc++
Foo.pass : Foo.test Foo.req
./Foo.test | diff Foo.req - 2>&1 > Foo.errors
touch $@
>
> Lakos's book is very insightful though. And then I discovered Python and
> since then most of my hacking in C++ has been on a hold..
>
> > In the Zope world, I think this has to translate to somthing like:
> >
> > 1. Each Python module should have a set of associated tests, which would by
> > preference live inside the "if __name__ == '__main__'" block at the bottom
> > of the module (an alternative would be to use Tim Peters' DocTest stuff,
> > which embeds the unit tests in docstrings). One would then have a script,
> > like the one which compiles all the Python modules during installation,
> > to run these modules (perhaps using some fancy dependency analysis based
> > on the import statements?)
>
> How would this work for things which use the Zope framework heavily, though?
> It's perfectly possible to do associate somekind of unit testing with
> Python modules, but the integration with the Zope framework seems to require
> having to use the framework in order to do the tests. That could slow the
> tests down a lot or make them too hard to perform, and the philosophy of
> these tests is that they should run quickly and should be easy to run, so
> you'll run them often.
Here is how I am approaching this with a small Product I am working on now:
* The "core" business logic is Zope-agnostic (doesn't import *anything*
Zopish); I test these modules using PyUnit (using a shell script, for
the nonce).
* The __init__ module for the Product imports the "core" modules and
derives "Zopish" subclasses from them, mixing in things like
OFS.SimpleItem and ObjectManager. I don't test these classes at all,
since they literally have no distinct methods (I think the only member
is 'meta_type'). It also declares the factory methods and management
interface, and registers the "Zopish" classes in its 'initialize()'.
* An alternate is to have the __init__ module register the "core" clases
as base classes; then create another "view" product which holds
ZClasses derived from them (I am beginning to think that this is a
higher-productivity technique, since tweaking the DTML is so much
simpler). The ZClasses have to be tested via ZClient and diff, as in
my original #2 below.
>
> > 2. For testing ZClasses, I am afraid that some kind of ZClient-based test
> > will be required. Each test would:
> >
> > * Generate a suitably-unique folder name.
> >
> > * Construct a folder of that name off the root of the ZODB.
>
> Or perhaps in some special 'scratchpad area'.
That works too. The "JUnit" tests all try to guarantee that no one test run
leaves anything lying around which might interfere with a subsequent test, which
is why I was randomizing the folder name -- even if the cleanup step barfed, you
would still never carry over artifacts.
--
=========================================================
Tres Seaver tseaver@palladion.com 713-523-6582
Palladion Software http://www.palladion.com