如何用getmembers()获取模块__name__ == '__main__'块内的测试函数
解决方案
首先明确问题根源:if __name__ == '__main__' 包裹的代码仅在模块作为主入口直接运行时才会执行,普通import导入模块时__name__值为模块名,该代码块完全不执行,里面定义的函数根本不会注册到模块对象上,因此getmembers()无法获取。
方案1:重构测试模块(推荐,符合Python最佳实践)
把测试函数移到代码块外,仅将初始化逻辑封装后放在if __name__ == '__main__'内,既避免导入时自动执行初始化,也能正常获取测试函数名。
修改后的test_oauth.py
class Tokens(): ## create access token based on data collected from POST request # 测试函数移到外层 def test_create_client_access_token_structure(): # ... def test_access_token_two_hour_expiry_time(): # ... if __name__ == '__main__': # 仅把初始化逻辑放在块内 access_tokens = Tokens() # 此处可添加执行测试的逻辑,比如调用测试框架入口
原有收集代码无需任何修改即可正常获取所有test前缀的测试函数名。
方案2:静态解析源码(无需修改测试模块)
如果不能改动测试模块的结构,可以用ast模块直接静态解析测试文件的源码,不需要导入模块,直接提取if __name__ == '__main__'块内的test前缀函数名。
修改后的collect_test_names.py
import ast def test_names_collector(test_file_path: str): test_names = [] # 读取源码解析为AST语法树 with open(test_file_path, 'r', encoding='utf-8') as f: tree = ast.parse(f.read()) # 遍历顶层节点查找if __name__ == '__main__'块 for node in ast.walk(tree): if isinstance(node, ast.If): # 校验if判断条件是否符合__name__ == '__main__'的特征 try: if (isinstance(node.test, ast.Compare) and isinstance(node.test.left, ast.Name) and node.test.left.id == '__name__' and isinstance(node.test.comparators[0], ast.Constant) and node.test.comparators[0].value == '__main__'): # 遍历块内节点,提取test前缀的函数定义 for sub_node in node.body: if isinstance(sub_node, ast.FunctionDef) and sub_node.name.startswith('test_'): test_names.append(sub_node.name) except: continue return test_names # 调用示例 test_names_list = test_names_collector(test_file_path='test_oauth.py')
注意:该方案仅解析静态代码,如果函数名是动态生成的会无法识别,仅适用静态定义函数的场景。
内容的提问来源于stack exchange,提问作者tigertiger
相关产品推荐
相关产品推荐

