Exhaustive Unit Testing

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Fri Nov 28 05:14:51 EST 2008


On Fri, 28 Nov 2008 00:06:01 -0800, bearophileHUGS wrote:

>>For this to change wouldn't be a little change, it would be a large
>>change.<
> 
> I see, then my proposal has little hope, I presume. I'll have to keep
> moving functions outside to test them and move them inside again when I
> want to run them.

Not so. You just need to prevent the nested functions from being garbage 
collected.

def foo(x):
    if not hasattr(foo, 'bar'):
        def bar(y):
            return x+y
        def foobar(y):
            return 3*y-y**2        
        foo.bar = bar
        foo.foobar = foobar
    return foo.bar(3)+foo.foobar(3)


However, note that there is a problem here: foo.bar will always use the 
value of x as it were when it was called the first time, *not* the value 
when you call it subsequently:

>>> foo(2)
5
>>> foo(3000)
5

Because foo.foobar doesn't use x, it's safe to use; but foo.bar is a 
closure and will always use the value of x as it was first used. This 
could be a source of puzzling bugs.

There are many ways of dealing with this. Here is one:

def foo(x):
    def bar(y):
        return x+y
    def foobar(y):
        return 3*y-y**2        
    foo.bar = bar
    foo.foobar = foobar
    return bar(3)+foobar(3)

I leave it as an exercise for the reader to determine how the behaviour 
of this is different to the first version.


-- 
Steven



More information about the Python-list mailing list