httprunner原始碼學習(三)__make()
阿新 • • 發佈:2022-01-18
mian_make()方法的第12行執行此方法;
打眼一看有點複雜,作者註釋的意思大概是使用絕對路徑建立testcase,生成pytest檔案並快取;
還是來逐行看吧。
- 31行之前都是對目錄/檔案的處理(.json .yaml .py)
- 40行讀取了 .json .yaml 檔案內容,開始進行處理(提取、排序等)
- 42-53行是對異常情況的處理(config不存在、config沒有name欄位、config不是字典等)
- 第59行開始就是httprunner的核心之一了,用例生成
- 第61行呼叫了自定義方法:make_testcase,我們去下面會研究一下這個方法
# httprunner/make.py :: __make def __make(tests_path: Text) -> NoReturn: """ make testcase(s) with testcase/testsuite/folder absolute path generated pytest file path will be cached in pytest_files_made_cache_mapping Args: tests_path: should be in absolute path """ logger.info(f"make path: {tests_path}") test_files = [] if os.path.isdir(tests_path): # 是目錄 files_list = load_folder_files(tests_path) # 自定義方法,作用是返回這個目錄下所有以.yml/.yaml/.json/_test.py結尾的檔案,返回值是個list。這個遞迴演算法也很有嚼頭,建議食用。 test_files.extend(files_list) # 將返回的list存入 test_files elif os.path.isfile(tests_path): # 如果不是目錄 test_files.append(tests_path) # 直接存入 test_files else: raise exceptions.TestcaseNotFound(f"Invalid tests path: {tests_path}") for test_file in test_files: if test_file.lower().endswith("_test.py"): # 如果檔名小寫後以_test.py結尾 pytest_files_run_set.add(test_file) # pytest_files_run_set 是定義在 make.py 的一個全域性變數,set型別。 continue try: test_content = load_test_file(test_file) # 自定義方法,作用是根據字尾判斷檔案型別(yaml/json),並返回讀取之後的內容(dict) except (exceptions.FileNotFound, exceptions.FileFormatError) as ex: logger.warning(f"Invalid test file: {test_file}\n{type(ex).__name__}: {ex}") continue if not isinstance(test_content, Dict): # 如果test_content不是dict logger.warning( f"Invalid test file: {test_file}\n" f"reason: test content not in dict format." ) continue # api in v2 format, convert to v3 testcase if "request" in test_content and "name" in test_content: # 如果request 和 name 在讀好的json/yaml檔案的第一層,執行ensure_testcase_v3_api方法 test_content = ensure_testcase_v3_api(test_content) if "config" not in test_content: logger.warning( f"Invalid testcase/testsuite file: {test_file}\n" f"reason: missing config part." ) continue elif not isinstance(test_content["config"], Dict): logger.warning( f"Invalid testcase/testsuite file: {test_file}\n" f"reason: config should be dict type, got {test_content['config']}" ) continue # ensure path absolute test_content.setdefault("config", {})["path"] = test_file # 給config新增一個鍵值對: {"path": test_file} # testcase if "teststeps" in test_content: try: testcase_pytest_path = make_testcase(test_content) pytest_files_run_set.add(testcase_pytest_path) except exceptions.TestCaseFormatError as ex: logger.warning( f"Invalid testcase file: {test_file}\n{type(ex).__name__}: {ex}" ) continue # testsuite elif "testcases" in test_content: try: make_testsuite(test_content) except exceptions.TestSuiteFormatError as ex: logger.warning( f"Invalid testsuite file: {test_file}\n{type(ex).__name__}: {ex}" ) continue # invalid format else: logger.warning( f"Invalid test file: {test_file}\n" f"reason: file content is neither testcase nor testsuite" )