Exhaustive Unit Testing

Fuzzyman fuzzyman at gmail.com
Sat Nov 29 10:41:24 EST 2008


On Nov 29, 3:33 am, "Emanuele D'Arrigo" <man... at gmail.com> wrote:
> On Nov 29, 12:35 am, Fuzzyman <fuzzy... at gmail.com> wrote:
>
> > Your experiences are one of the reasons that writing the tests *first*
> > can be so helpful. You think about the *behaviour* you want from your
> > units and you test for that behaviour - *then* you write the code
> > until the tests pass.
>
> Thank you Michael, you are perfectly right in reminding me this. At
> this particular point in time I'm not yet architecturally foresighted
> enough to be able to do that. While I was writing the design documents
> I did write the list of methods each object would have needed and from
> that description theoretically I could have made the tests first. In
> practice, while eventually writing the code for those methods, I've
> come to realize that there was a large amount of variance between what
> I -thought- I needed and what I -actually- needed. So, had I written
> the test before, I would have had to rewrite them again. That been
> said, I agree that writing the tests before must be my goal. I hope
> that as my experience increases I'll be able to know beforehand the
> behaviors I need from each method/object/module of my applications.
> One step at the time I'll get there... =)
>


Personally I find writing the tests an invaluable part of the design
process. It works best if you do it 'top-down'. i.e. You have a
written feature specification (a user story) - you turn this into an
executable specification in the form of a functional test.

Next to mid level unit tests and downwards - so your tests become your
design documents (and the way you think about design), but better than
a document they are executable. So just like code conveys intent so do
the tests (it is important that tests are readable).

For the situation where you don't really know what the API should look
like, Extreme Programming (of which TDD is part) includes a practise
called spiking. I wrote a bit about that here:

http://www.voidspace.org.uk/python/weblog/arch_d7_2007_11_03.shtml#e867

Mocking can help reduce the number of code paths you need to test for
necessarily complex code. Say you have a method that looks something
like:

def method(self):
    if conditional:
        # do stuff
    else:
        # do other stuff
    # then do more stuff

You may be able to refactor this to look more like the following

def method(self):
    if conditional:
        self.method2()
    else:
        self.method3()
    self.method4()

You can then write unit tests that *only* tests methods 2 - 4 on their
own. That code is then tested. You can then test method by mocking out
methods 2 - 4 on the instance and only need to test that they are
called in the right conditions and with the right arguments (and you
can mock out the return values to test that method handles them
correctly).

Mocking in Python is very easy, but there are plenty of mock libraries
to make it even easier. My personal favourite (naturally) is my own:

http://www.voidspace.org.uk/python/mock.html

All the best,

Michael
--
http://www.ironpythoninaction.com/



> Manu




More information about the Python-list mailing list