unit test nested functions

A

Andy

How can you unit test nested functions? Or do you have to pull them out to
unit test them, which basically means I will never use nested functions.

Also, same thing with private member functions protected by __. Seems like
there is a conflict there between using these features and unit testing.

Andy
 
A

Andrew Dalke

Andy said:
How can you unit test nested functions?

I can't think of a good way. When I write a nested function it's because
the function uses variables from the scope of the function in which it's
embedded, which means it makes little sense to test it independent of the
larger function.

My tests in that case are only of the enclosing function.
Or do you have to pull them out to
unit test them, which basically means I will never use nested functions.

You don't test every line in a function by itself, right? Nor
every loop in a function. It should be possible to test the outer
function enough that the implementation detail - of using an inner
function - doesn't make much difference.
Also, same thing with private member functions protected by __. Seems
like there is a conflict there between using these features and unit
testing.

In that case the spec defined that the real function name is of
.... def __sing(self):
.... print "I don't see any Vikings."
....
I've found though that the double-leading-underscore is overkill.
Using a single underscore is enough of a hint that the given
method shouldn't be called directly.

Then again, I don't write enough deep hierarchies where I need
to worry about a subclass implementation using the same private
name as a superclass.
Andrew
(e-mail address removed)
 
R

Raymond Hettinger

[Andy]
How can you unit test nested functions? Or do you have to pull them out to
unit test them, which basically means I will never use nested functions.

Several commons use cases (closures and factory functions) ultimately
expose the inner function through the return value. If that is the
case, the answer is simple, call the enclosing function and then run
the test on the result.

If the inner function never gets exposed, an argument could be made
that you don't want to write a test for it -- that the inner function
is just an implementation detail. This is black box testing and
consistent with a test driven development approach.

For whitebox testing, you could make an inner function visible by
binding it to the enclosing function's attribute namespace.

def f(x):
def g(y):
. . .
f.g = g # make g visible as an attribute of f
. . .


Raymond
 
B

Benji York

Raymond said:
[Andy]
How can you unit test nested functions?
For whitebox testing, you could make an inner function visible by
binding it to the enclosing function's attribute namespace.

def f(x):
def g(y):
. . .
f.g = g # make g visible as an attribute of f
. . .

Note that when using this technique, f.g will not be bound until after
you call the function:
.... def g(y):
.... pass
.... f.g = g
....Traceback (most recent call last):
<function g at 0xb7df3e2c>
 
R

Raymond Hettinger

[Andy]
[Raymond Hettinger]
[Benji York]
Note that when using this technique, f.g will not be bound until after
you call the function:

That is a feature, not a bug. The inner function isn't even created
until the outer function is run.
z = 30
def g(y):
return 10
return 20
2 0 LOAD_CONST 1 (30)
3 STORE_FAST 1 (z)

3 6 LOAD_CONST 2 (<code object g at 00A33660,
file "<pyshell#37>", line 3>)
9 MAKE_FUNCTION 0
12 STORE_FAST 2 (g)

5 15 LOAD_CONST 3 (20)
18 RETURN_VALUE

The MAKE_FUNCTION step is where g comes into existence. That is a
run-time operation, not compile time.

If you are willing to be tricky, it is possible to write an accessor
function that goes into f.func_code.co_consts, finds the code object
whose co_name attribute is 'g', builds a wrapper function using
types.FunctionType, and returns the result for unittesting. But that
is not for the faint of heart ;-)



Raymond
 
B

Benji York

Raymond said:
[Benji York]
Note that when using this technique, f.g will not be bound until after
you call the function:


That is a feature, not a bug. The inner function isn't even created
until the outer function is run.

I'm fully aware of that. I just didn't want the OP get bit by it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,262
Messages
2,571,310
Members
47,977
Latest member
MillaDowdy

Latest Threads

Top