469,927 Members | 1,322 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,927 developers. It's quick & easy.

unit test nested functions

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
Jul 23 '05 #1
5 3021
Andy wrote:
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
the form "_<CLASSNAME>__<METHODNAME>". For example
class Spam: .... def __sing(self):
.... print "I don't see any Vikings."
.... spam = Spam()
spam._Spam__sing() 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
da***@dalkescientific.com

Jul 23 '05 #2
[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

Jul 23 '05 #3
Raymond Hettinger wrote:
[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 f(x): .... def g(y):
.... pass
.... f.g = g
.... f <function f at 0xb7df3df4> f.g Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'function' object has no attribute 'g' f(1)
f.g

<function g at 0xb7df3e2c>
--
Benji York
Jul 23 '05 #4
> > [Andy]
How can you unit test nested functions?
[Raymond Hettinger]
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
. . .

[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.
def f(x): z = 30
def g(y):
return 10
return 20
from dis import dis
dis(f)

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

Jul 23 '05 #5
Raymond Hettinger wrote:
[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.
--
Benji York
Jul 23 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

7 posts views Thread by block111 | last post: by
5 posts views Thread by sylcheung | last post: by
8 posts views Thread by micklee74 | last post: by
5 posts views Thread by VvanN | last post: by
2 posts views Thread by bearophileHUGS | last post: by
5 posts views Thread by shuisheng | last post: by
1 post views Thread by rich_sposato | last post: by
6 posts views Thread by Vyacheslav Maslov | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.