![](/img/trans.png)
[英]getting a python function of functionType for a nested function with recursion
[英]Pass closure to FunctionType in function
我有这样的代码:
class A():
def __init__(self, a):
self.a = a
def outer_method(self):
def inner_method():
return self.a +1
return inner_method()
我想为inner_method
编写测试。 为此,我正在使用这样的代码:
def find_nested_func(parent, child_name):
"""
Return the function named <child_name> that is defined inside
a <parent> function
Returns None if nonexistent
"""
consts = parent.__code__.co_consts
item = list(filter(lambda x:isinstance(x, CodeType) and x.co_name==child_name, consts ))[0]
return FunctionType(item, globals())
用find_nested_func(A().outer_method, 'inner_method')
调用它,但是在调用'FunctionType'时失败,因为无法创建函数,因为'self.a'在函数停止成为内部函数时就停止存在。 我知道构造FunctionType可以将可以解决此问题的闭包作为参数来接受,但是我不知道如何使用它。 我该如何通过?
它给出的错误是下一个错误:
return FunctionType(item, globals())
TypeError: arg 5 (closure) must be tuple
为什么要尝试测试inner_method
? 在大多数情况下,您应该只测试公共API的一部分。 outer_method
是A
的公共API的一部分,因此请对其进行测试。 inner_method
是可以更改的实现细节:如果您决定重命名该怎么办? 如果在不修改external_method的外部可见行为的情况下对其进行了少量重构,该outer_method
办? A
类A
用户没有(简单)的调用inner_method
。 单元测试通常仅用于测试您的类用户可以调用的东西(我假设这些是用于单元测试的,因为集成测试这种细粒度的方法会很奇怪-并且相同的原理仍然适用)。
实际上,由于其他一些原因(包括变量捕获),提取另一个函数范围内定义的函数会遇到问题。 您无法知道inner_method
仅捕获self
或outer_method
执行某些逻辑并计算inner_method
使用的某些变量。 例如:
class A:
def outer_method():
b = 1
def inner_method():
return self.a + b
return inner_method()
另外,您可能在函数定义周围有控制语句,因此如果不运行outer_method
,就无法确定使用哪个定义。 例如:
import random
class A:
def outer_method():
if random.random() < 0.5:
def inner_method():
return self.a + 1
else:
def inner_method():
return self.a + 2
return inner_method()
您不能在这里提取inner_method
,因为它们有两个,并且您不知道实际使用的是哪个,直到您运行outer_method
。
因此,只是不要测试inner_method
。
如果inner_method
确实非常复杂,以至于您想inner_method
进行测试(如果这样做,则有原则的测试表明您应该模拟出它的用法,例如,在outer_method
中的outer_method
),然后将其outer_method
“私有”方法在A
:
class A:
def _inner_method(self):
return self.a + 1
def outer_method(self):
return self._inner_method()
原则上的测试表明,您实际上不应该测试下划线方法,但有时有必要这样做。 通过这种方式,您可以像测试其他任何方法一样测试_inner_method
。 然后,在测试outer_method
,可以通过执行a._inner_method = Mock()
来模拟它(其中a
是被测试的A
对象)。
另外,请使用class A
。 除非有父类,否则不需要括号。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.