所以我在我的Python27/Lib 目录中环顾四周...
unittest.main 实际上是一个类的别名,unittest.TestProgram。所以发生的事情是你构造了一个这个实例,它的__init__ 运行,它进行了一堆健全性检查和配置,包括你调用它的模块的动态导入(它使用__import__ 函数,与__main__ 作为要导入的模块的名称,默认情况下)。所以现在它有一个 self.module 属性,其中包含一个代表您的源的模块对象。
最终,它得到了这段代码:
self.test = self.testLoader.loadTestsFromModule(self.module)
其中self.testLoader 是unittest.TestLoader 的一个实例。该方法包含以下内容:
for name in dir(module):
obj = getattr(module, name)
if isinstance(obj, type) and issubclass(obj, case.TestCase):
tests.append(self.loadTestsFromTestCase(obj))
因此它使用模块对象的dir 来获取您定义的所有全局变量(包括类)的名称,将其过滤到仅派生自unittest.TestCase 的类(在本地,case.TestCase 是别名),然后在这些类中查找测试方法以添加到tests 列表中。该搜索的行为类似:
def isTestMethod(attrname, testCaseClass=testCaseClass,
prefix=self.testMethodPrefix):
return attrname.startswith(prefix) and \
hasattr(getattr(testCaseClass, attrname), '__call__')
testFnNames = filter(isTestMethod, dir(testCaseClass))
所以它使用类的dir 来获取要尝试的名称列表,查找具有这些名称的属性,并选择那些以self.testMethodPrefix 开头(默认为'test')并且可调用的属性(反过来,有一个__call__ 属性)。 (我真的很惊讶他们在这里没有使用内置的callable 函数。我想这是为了避免使用嵌套类。)