1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4import os 5import sys 6import json 7import argparse 8 9# command line parameters 10parser = argparse.ArgumentParser() 11parser.add_argument("--module_list", dest="module_list", required=True, 12 help='module list', type=str) 13parser.add_argument("--case_root", dest="case_root", required=True, 14 help='case root', type=str) 15parser.add_argument("--result_file", dest="result_file", required=True, 16 help='result file', type=str) 17 18 19class PsrModuleAttr: 20 def __init__(self, case_root, result_file, module_list): 21 self.case_root = case_root 22 self.module_list = json.loads(module_list) 23 self.result_file = result_file 24 25 self.surpport_run_case_mod = ["env_card", "env_onecard", "env_single", "env_cluster"] 26 27 @staticmethod 28 def get_case_file_pytestmark(case_root, package, case_name, class_name=None, func_name=None): 29 """ 30 get pytestmark info from testcase name, function/class name 31 """ 32 root_path = os.path.abspath(os.path.join(package, "..")) 33 package_name = package.split(os.sep)[-1] 34 35 init_py = os.path.join(package, "__init__.py") 36 if not os.path.exists(init_py): 37 fd = os.open(init_py, os.O_WRONLY|os.O_CREAT, 0o644) 38 os.write(fd, str.encode("")) 39 os.close(fd) 40 41 sys.path.insert(0, case_root) 42 sys.path.insert(0, package) 43 sys.path.insert(0, root_path) 44 45 case_name_pkg = __import__(package_name + "." + case_name, fromlist=case_name.split(".")[-1:]) 46 47 if func_name and not class_name: 48 function_pkg = getattr(case_name_pkg, func_name) 49 pytestmark = getattr(function_pkg, "pytestmark") 50 elif func_name and class_name: 51 class_pkg = getattr(case_name_pkg, class_name) 52 function_pkg = getattr(class_pkg, func_name) 53 pytestmark = getattr(function_pkg, "pytestmark") 54 elif not func_name and class_name: 55 class_pkg = getattr(case_name_pkg, class_name) 56 pytestmark = getattr(class_pkg, "pytestmark", None) 57 else: 58 return None 59 60 pytestmark_info = list() 61 if pytestmark: 62 for mark in pytestmark: 63 name = mark.name 64 # none attr stype 65 if name != "attr": 66 pytestmark_info.append(name) 67 else: 68 pytestmark_info.append(list(mark.kwargs.values())[0]) 69 70 return pytestmark_info 71 72 def parser_pytest_mark_info(self, pytestmark, package, case_name, 73 test_object_name): 74 """ 75 parse mark as fixed format, only parse "run_case_mod" , "env_type", "component", "feature" 76 """ 77 pytest_mark_info = {} 78 is_parser_mark_err = False 79 for mark_info in pytestmark: 80 if isinstance(mark_info, (str,)): 81 mark_infos = [mark_info] 82 elif isinstance(mark_info, (list, tuple)): 83 mark_infos = mark_info 84 else: 85 mark_infos = list() 86 87 for tmp_mark_info in mark_infos: 88 if tmp_mark_info in self.surpport_run_case_mod: 89 if not pytest_mark_info.get("run_case_mod"): 90 pytest_mark_info["run_case_mod"] = tmp_mark_info 91 else: 92 print('{0}/{1}:{2} env_type can only be one of env_onecard","env_single","env_cluster"' \ 93 .format(package, case_name, test_object_name)) 94 is_parser_mark_err = True 95 96 elif str(tmp_mark_info).startswith("platform_"): 97 if not pytest_mark_info.get("env_type"): 98 env_type = list() 99 pytest_mark_info["env_type"] = env_type 100 pytest_mark_info.get("env_type").append(tmp_mark_info) 101 102 elif str(tmp_mark_info).startswith("component_"): 103 if not pytest_mark_info.get("component"): 104 pytest_mark_info["component"] = tmp_mark_info 105 elif str(tmp_mark_info).startswith("feature_"): 106 if not pytest_mark_info.get("feature"): 107 pytest_mark_info["feature"] = tmp_mark_info 108 109 # when env_type not in ["env_onecard", "env_single", "env_cluster"], report error 110 if not pytest_mark_info.get("run_case_mod"): 111 print('{0}/{1}:{2} env_type must be one of "env_onecard", "env_single", "env_cluster"' \ 112 .format(package, case_name, test_object_name)) 113 is_parser_mark_err = True 114 115 if is_parser_mark_err: 116 return None 117 return pytest_mark_info 118 119 def get_function_based_cases(self, package, case_name, function_list): 120 attrs = {"package": package, "case_name": case_name, "function_list": [], "class": {}} 121 has_psr_func_list = list() 122 for function in function_list: 123 # func_name has special keyword, in pytest parametrize case, do trunction 124 if str(function).__contains__('[') or str(function).__contains__('('): 125 print("abnormal func_name {} has been to be filter".format(function)) 126 func_name = function.split('[')[0].split('(')[0] 127 if func_name in has_psr_func_list: 128 continue 129 has_psr_func_list.append(func_name) 130 else: 131 func_name = function 132 133 pytestmark = self.get_case_file_pytestmark(self.case_root, package, case_name, func_name=func_name) 134 function_attr = {"function": func_name} 135 pytest_mark_info = self.parser_pytest_mark_info(pytestmark, package, case_name, func_name) 136 if pytest_mark_info is None: 137 attrs_list.append(None) 138 continue 139 function_attr.update(pytest_mark_info) 140 attrs.get("function_list").append(function_attr) 141 return attrs 142 143 def get_class_based_cases(self, package, case_name, function_list, class_info): 144 attrs = {"package": package, "case_name": case_name, "function_list": [], "class": class_info} 145 # class based testcase satisfying condition 146 pytestmark = self.get_case_file_pytestmark(self.case_root, package, case_name, class_name=class_info) 147 if pytestmark: 148 tmp_attrs = {} 149 tmp_class_info = {"class_name": class_info} 150 pytest_mark_info = self.parser_pytest_mark_info(pytestmark, package, case_name, class_info) 151 if pytest_mark_info is None: 152 attrs_list.append(None) 153 return None 154 tmp_attrs.update(pytest_mark_info) 155 tmp_class_info.update(pytest_mark_info) 156 attrs["class"] = tmp_class_info 157 for function in function_list: 158 function_attr = {"function": function} 159 function_attr.update(tmp_attrs) 160 attrs.get("function_list").append(function_attr) 161 # function based testcase satisfying condition 162 else: 163 tmp_class_info = {"class_name": class_info} 164 has_psr_func_list = list() 165 for function in function_list: 166 # func_name has special keyword, in pytest parametrize case, do trunction 167 if str(function).__contains__('[') or str(function).__contains__('('): 168 print("abnormal func_name {} has been to be filter".format(function)) 169 func_name = function.split('[')[0].split('(')[0] 170 if func_name in has_psr_func_list: 171 continue 172 has_psr_func_list.append(func_name) 173 else: 174 func_name = function 175 pytestmark = self.get_case_file_pytestmark( 176 self.case_root, package, case_name, 177 func_name=func_name, class_name=class_info) 178 function_attr = {"function": func_name} 179 pytest_mark_info = self.parser_pytest_mark_info( 180 pytestmark, package, case_name, func_name) 181 if pytest_mark_info is None: 182 attrs_list.append(None) 183 continue 184 tmp_class_info.update(pytest_mark_info) 185 function_attr.update(pytest_mark_info) 186 attrs.get("function_list").append(function_attr) 187 attrs["class"] = tmp_class_info 188 return attrs 189 190 def parser_module_attr(self): 191 attrs_list = list() 192 for module in self.module_list: 193 package = module.get("package", "") 194 case_name = module.get("module", "").split(".")[0] 195 function_list = module.get("function_list", "") 196 class_info = module.get("class", "") 197 print("parser_module_attr start") 198 199 # testcase file contains only function based (no class based) testcases 200 if not class_info: 201 attrs = self.get_function_based_cases(package, case_name, function_list) 202 # testcase file contains class based testcases 203 else: 204 attrs = self.get_class_based_cases(package, case_name, function_list, class_info) 205 if attrs is None: 206 continue 207 208 attrs_list.append(attrs) 209 210 return attrs_list 211 212 def main(self): 213 attrs_list = self.parser_module_attr() 214 215 if not attrs_list: 216 sys.exit(1) 217 218 fd = os.open(self.result_file, os.O_WRONLY|os.O_CREAT, 0o644) 219 os.write(fd, str.encode(json.dumps(attrs_list))) 220 os.close(fd) 221 222 print("attrs_list : %s" % attrs_list) 223 224 225if __name__ == '__main__': 226 args = parser.parse_args() 227 input_args = (args.case_root, args.result_file, args.module_list) 228 229 psr_ins = PsrModuleAttr(*input_args) 230 psr_ins.main() 231