Python自省:在运行时定义动态类方法



我试图创建一个单元测试,检查mymodule中的每个函数都有自己的TestCase实例。
为了减少样板代码和手工工作,我想使用自省/反射来动态地将lambda函数作为类方法添加到最初为空的类Test_TestCases。下面的代码可以工作——它确实添加了lambdas作为类方法,unittest.main()发现并正确调用它们。

import unittest
from unittest import TestCase
import mymodule
class Test_TestCases(TestCase):
"""Class whose test_* methods will be created during runtime."""
    pass
################################################################################
if __name__ == "__main__":
    for item in dir(mymodule):
        attr = getattr(pws, item)
        if callable(attr):
            testname = "Test_%s" % item
            setattr(Test_TestCases, "test_%s_is_tested" % item,
                    lambda self: self.assertTrue(testname in globals()) and
                    issubclass(getattr(globals(), testname), TestCase))
    unittest.main()

问题是,即使我的单元测试模块中有未测试的函数,所有的测试都成功了。
经过一番尝试,我发现每次调用lambda时,变量testname都具有相同的值。
为了重现性,我可以将问题最小化到这段代码:

lambdas = []
for i in range(5):
    lambdas.append(lambda: str(i))
print ", ".join(f() for f in lambdas)

我希望这样的输出:

0, 1, 2, 3, 4

但是我得到:

4, 4, 4, 4, 4

看起来lambda是惰性初始化的。
有没有人能解释一下这种行为,或者给我一个提示,告诉我如何才能正确地完成我的目标?

Thanks in advance

使用另一个包装器函数影子testname:

def assertion(testname=testname):
    def function(self):
        return self.assertTrue(testname in globals()) and issubclass(getattr(globals(), testname), TestCase))
    return function
setattr(Test_TestCases, "test_%s_is_tested" % item, assertion())

最新更新