argparse子命令行可用但测试时报AttributeError问题
问题解决:argparse子命令参数在测试中报错AttributeError
问题原因
你在list方法内部用argparse定义了可选的query参数,命令行运行时因为传入了list子命令,argparse能正常解析出query(不传时为None);但直接调用Handler().list()的测试用例里,sys.argv没有list这个子命令参数,导致argparse未触发该子命令的参数解析,返回的Namespace对象里根本没有query属性,所以执行if args.query:时会报错。
解决方案
方案一:测试时补全sys.argv参数
在测试用例中通过patch修改sys.argv,补上list子命令,让argparse能正常解析出query参数(值为None):
def test_basic(self): """Test that list command prints correct string.""" with patch("todo.open", mock_open(read_data="One\nTwo\n")), patch('sys.argv', ['file.py', 'list']): Handler().list() expected = dedent( """\ 1 One 2 Two --- 2 item(s) """ ) self.assertPrinted(expected)
方案二:重构代码分离职责(推荐)
把命令行解析逻辑和业务逻辑分开,让list方法直接接受query参数,不再依赖argparse从命令行读取:
1. 修改Handler的list方法
def list(self, query=None): # 原来的业务逻辑直接使用query参数 if query: # 处理带查询条件的逻辑 ... else: # 处理无查询条件的逻辑 ...
2. 在脚本入口处理argparse解析
if __name__ == "__main__": parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(dest="command") parser_list = subparsers.add_parser("list") parser_list.add_argument('query', type=str, nargs='?') args = parser.parse_args() handler = Handler() if args.command == "list": handler.list(args.query)
这样测试时直接调用Handler().list()即可,无需关心命令行参数,代码结构更清晰,测试也更简便。
内容的提问来源于stack exchange,提问作者Bloop
相关产品推荐
相关产品推荐

