解析cli.py
main():主函数,解析接收到的命令,并根据接收到的不同命令调用不同函数,主要有:main_run(),main_scaffold(),main_har2case(),main_make()
main_run: 供main中run命令调用的函数,如果要直接调用main_run函数,需要传入hrun run后边的参数,
最后把处理过的路径,其他参数和--tb=short一起传递给了pytest.main()
init_parser_run:给main函数中添加run子命令
main_hrun_alias
main_make_alias
main_har2case_alias
这三个是对命令别名进行解析,最后都调用main()
import argparse import enum import os import sys import pytest from loguru import logger from sentry_sdk import capture_message from httprunner import __description__, __version__ from httprunner.compat import ensure_cli_args from httprunner.ext.har2case import init_har2case_parser, main_har2case from httprunner.make import init_make_parser, main_make from httprunner.scaffold import init_parser_scaffold, main_scaffold from httprunner.utils import init_sentry_sdk init_sentry_sdk() def init_parser_run(subparsers): #创建子命令方法 sub_parser_run = subparsers.add_parser( "run", help="Make HttpRunner testcases and run with pytest." ) return sub_parser_run def main_run(extra_args) -> enum.IntEnum: #接收传递过来的额外参数 capture_message("start to run") # keep compatibility with v2 extra_args = ensure_cli_args(extra_args) #为了兼容旧版本命令做了下转换 tests_path_list = [] extra_args_new = [] for item in extra_args: if not os.path.exists(item): # item is not file/folder path extra_args_new.append(item) else: # item is file/folder path tests_path_list.append(item) #判读路径或者文件是否存在,如果存在则存到列表中 if len(tests_path_list) == 0: #如果case路径没有,则报错 # has not specified any testcase path logger.error(f"No valid testcase path in cli arguments: {extra_args}") sys.exit(1)#有异常退出 testcase_path_list = main_make(tests_path_list)#返回待测试的文件集 if not testcase_path_list: #再check下main_make之后的文件集,是否为空,空则报错 logger.error("No valid testcases found, exit 1.") sys.exit(1) if "--tb=short" not in extra_args_new: extra_args_new.append("--tb=short") extra_args_new.extend(testcase_path_list)#把测试文件集加到参数列表后边 logger.info(f"start to run tests with pytest. HttpRunner version: {__version__}") return pytest.main(extra_args_new)#针对新的参数列表调用pytest.main函数 def main(): """ API test: parse command line options and run commands. """ parser = argparse.ArgumentParser(description=__description__)#argparse 是 Python 内置的一个用于命令项选项与参数解析的模块,创建一个解析对象 parser.add_argument( "-V", "--version", dest="version", action="store_true", help="show version" )#定义单个的命令行参数应当如何解析 subparsers = parser.add_subparsers(help="sub-command help")#创建子命令对象 sub_parser_run = init_parser_run(subparsers)#创建子命令 sub_parser_scaffold = init_parser_scaffold(subparsers)#创建子命令 sub_parser_har2case = init_har2case_parser(subparsers)创建子命令 sub_parser_make = init_make_parser(subparsers)创建子命令 if len(sys.argv) == 1: # httprunner parser.print_help()#打印帮助信息 sys.exit(0)#程序正常结束 elif len(sys.argv) == 2: # print help for sub-commands if sys.argv[1] in ["-V", "--version"]: # httprunner -V print(f"{__version__}") elif sys.argv[1] in ["-h", "--help"]: # httprunner -h parser.print_help() elif sys.argv[1] == "startproject": # httprunner startproject sub_parser_scaffold.print_help() elif sys.argv[1] == "har2case": # httprunner har2case sub_parser_har2case.print_help() elif sys.argv[1] == "run": # httprunner run pytest.main(["-h"]) elif sys.argv[1] == "make": # httprunner make sub_parser_make.print_help() sys.exit(0) elif ( len(sys.argv) == 3 and sys.argv[1] == "run" and sys.argv[2] in ["-h", "--help"] ): # httprunner run -h pytest.main(["-h"]) sys.exit(0) #以上都是打印帮助信息 extra_args = [] if len(sys.argv) >= 2 and sys.argv[1] in ["run", "locusts"]: args, extra_args = parser.parse_known_args() else: args = parser.parse_args() #将参数(默认是sys.argv)转换问命名空间的属性,并返回命名空间 if args.version: print(f"{__version__}") sys.exit(0) #如果args中version参数为TRUE则打印version if sys.argv[1] == "run": sys.exit(main_run(extra_args)) #调用main_run函数并传命令外参数 elif sys.argv[1] == "startproject": main_scaffold(args) elif sys.argv[1] == "har2case": main_har2case(args) elif sys.argv[1] == "make": main_make(args.testcase_path) def main_hrun_alias(): """ command alias hrun = httprunner run """ if len(sys.argv) == 2: if sys.argv[1] in ["-V", "--version"]: # hrun -V sys.argv = ["httprunner", "-V"] elif sys.argv[1] in ["-h", "--help"]: pytest.main(["-h"]) sys.exit(0) else: # hrun /path/to/testcase sys.argv.insert(1, "run") else: sys.argv.insert(1, "run") main() def main_make_alias(): """ command alias hmake = httprunner make """ sys.argv.insert(1, "make") main() def main_har2case_alias(): """ command alias har2case = httprunner har2case """ sys.argv.insert(1, "har2case") main() if __name__ == "__main__": main()