• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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