Ejemplo n.º 1
0
def check_response_text(fields, response):
    error_info = ""
    log.debug(
        Template("fields: $fields, response: $response").substitute(
            fields=fields, response=response))
    if not fields:
        return error_info
    if not isinstance(fields, str):
        raise TypeError("neet to check fields is not a str")
    for text in fields.split(','):
        text = text.lstrip("'").lstrip('"').rstrip("'").rstrip('"')
        log.debug(Template("待校验的内容: $text").substitute(text=text))
        if isinstance(response, dict):
            # if not response.get(text):
            isempty = jmespath.search(text, response)
            if isempty is None:
                error_info += Template(
                    "接口响应内容没有待校验的字段:$t,响应内容:$res").substitute(t=text,
                                                              res=response)
        else:
            if text not in response:
                error_info += Template(
                    "接口响应内容没有待校验的字段:$t,响应内容:$res").substitute(t=text,
                                                              res=response)

    return error_info
Ejemplo n.º 2
0
    def send_text(self, msg, ats=None):
        """
        func: 发送钉钉群消息
        :param msg: text message conntent
        :param ats: phone list of to @, element "all" equal to @all
        :return:
        """
        timestamp, sign = self._secret()
        url_ = self.token
        url_ = url_ + "&timestamp={}&sign={}".format(timestamp, sign)
        log.debug('dingrobot complete url is: {}'.format(url_))
        if ats is None:
            ats = []
        text_msg = {"msgtype": "text", "text": {"content": msg}}

        at_info = {"atMobiles": [], "isAtAll": False}
        for item in ats:
            if item == "all":
                at_info["isAtAll"] = True
            elif isinstance(item, int):
                at_info["atMobiles"].append(item)
            else:
                pass
        text_msg["at"] = at_info
        header = {"Content-Type": "application/json"}
        with requests.post(url_, json.dumps(text_msg), headers=header) as res:
            log.info('dingrobot response is: {}'.format(res.text))
Ejemplo n.º 3
0
 def get(self):
     res = requests.get(url=self.url,
                        params=self.params,
                        headers=self.header)
     log.debug(
         string.Template("response json: $res").substitute(res=res.json()))
     return res
Ejemplo n.º 4
0
 def parse_case(self):
     """
     对所有用例根据sheetname进行转换
     :return:
     """
     all_sheets = {}
     mapper = settings.excel_fields
     new_excel_file = os.path.join(settings.old_testcase_file_path, "new_{}".format(os.path.split(self.file_name)[-1]))
     excel_helper = CaseWrite(list(self.all_sheets.keys()))
     for sheet_name, sheet in self.all_sheets.items():
         testcases = list(self._read_row(sheet))
         log.debug(Template("testcase: $testcases").substitute(testcases=testcases))
         testcases = self._format(testcases)
         all_sheets[sheet_name] = []
         if testcases:
             self.sheet_case = testcases[1:]
             all_sheets[sheet_name].append(self.testcase_switch())
         for case in self.sheet_case:
             data_list = [""] * 25
             data_list[mapper['order']] = case['order_index'] if case.get('order_index') else ""
             data_list[mapper['casename']] = case['tc_name'] if case.get('tc_name') else ""
             data_list[mapper['description']] = case['description'] if case.get('description') else ""
             data_list[mapper['url']] = case['url'] if case.get('url') else ""
             data_list[mapper['method']] = case['method'] if case.get('method') else ""
             data_list[mapper['params']] = case['params'] if case.get('params') else ""
             data_list[mapper['header']] = case['header'] if case.get('header') else ""
             data_list[mapper['interface_var']] = case['interface_var'] if case.get('interface_var') else ""
             data_list[mapper['wait_time']] = case['wait_time'] if case.get('wait_time') else ""
             data_list[mapper['verify_fields']] = case['verify_fields'] if case.get('verify_fields') else ""
             data_list[mapper['res_text']] = case['res_text'] if case.get('res_text') else ""
             data_list[mapper['module']] = case['test_task_key'] if case.get('test_task_key') else ""
             excel_helper.append(sheet_name, data_list)
Ejemplo n.º 5
0
 def _order_for_testcase(self, cases, base_num):
     """
     func:用于给所有测试用例编排执行顺序
     :param cases:
     :return:
     """
     orders = self._get_cases_orders(cases)
     log.debug(
         string.Template("**************$o****************").substitute(
             o=orders))
     max_num = max(orders) + 1 if orders else 1
     ordered = []
     for case in cases:
         try:
             order = int(case['order']) if case['order'] else None
         except Exception as e:
             log.error(
                 string.Template(
                     "integer order number error, error info: $e").
                 substitute(e=e))
             order = None
         if order:
             case['order'] = base_num + order
         else:
             case['order'] = base_num + max_num
             max_num += 1
         ordered.append(case)
     return ordered
Ejemplo n.º 6
0
 def parse_testsuite_fields_lines(self, content):
     """
     func: 解析测试sheet中局部变量、初始化数据、接口测试、数据恢复所在的行位置
     :param content: sheet所有行的数据
     :return: 局部变量、初始化数据、接口测试、数据恢复所在的行位置
     """
     lines_info = {}
     lines_info_result = {}
     if not isinstance(content, list):
         raise TypeError("params is not a list object")
     print(content)
     for num in range(0, len(content)):
         if '局部变量' == content[num][0].value:
             lines_info[self.testsuite_local_vars_line_name] = num
         if '初始化数据' == content[num][0].value:
             lines_info[self.testsuite_init_line_name] = num
         elif '接口测试' == content[num][0].value:
             lines_info[self.testsuites_testcase_line_name] = num
         elif '数据恢复' == content[num][0].value:
             lines_info[self.testsuites_restore_line_name] = num
     log.info(
         string.Template("line info: $lines_info").substitute(
             lines_info=lines_info))
     lines_info_order = sorted(lines_info.items(),
                               key=lambda x: x[1],
                               reverse=False)
     fields_num = len(lines_info_order)
     if fields_num == 4:
         lines_info_result[lines_info_order[0][0]] = (
             lines_info_order[0][1], lines_info_order[1][1])
         lines_info_result[lines_info_order[1][0]] = (
             lines_info_order[1][1], lines_info_order[2][1])
         lines_info_result[lines_info_order[2][0]] = (
             lines_info_order[2][1], lines_info_order[3][1])
         lines_info_result[lines_info_order[3][0]] = (
             lines_info_order[3][1], len(content))
     if fields_num == 3:
         lines_info_result[lines_info_order[0][0]] = (
             lines_info_order[0][1], lines_info_order[1][1])
         lines_info_result[lines_info_order[1][0]] = (
             lines_info_order[1][1], lines_info_order[2][1])
         lines_info_result[lines_info_order[2][0]] = (
             lines_info_order[2][1], len(content))
     elif fields_num == 2:
         lines_info_result[lines_info_order[0][0]] = (
             lines_info_order[0][1], lines_info_order[1][1])
         lines_info_result[lines_info_order[1][0]] = (
             lines_info_order[1][1], len(content))
     elif fields_num == 1:
         lines_info_result[lines_info_order[0][0]] = (
             lines_info_order[0][1], len(content))
     log.debug(
         string.Template("lines_info_result: $lines_info_result").
         substitute(lines_info_result=lines_info_result))
     return lines_info_result
Ejemplo n.º 7
0
 def __init__(self, api_info):
     self.api_info = api_info
     log.debug(
         string.Template("api_info: $api_info").substitute(
             api_info=self.api_info))
     self.method = self.api_info['method']
     self.url = self.api_info['url']
     self.params = self.api_info['params'] if self.api_info[
         'params'] else None
     self.header = self.api_info['header'] if self.api_info[
         'header'] else None
Ejemplo n.º 8
0
 def reg_compare(k, v, r):
     info = ""
     v = v.lstrip('<#reg>')
     res = jmespath.search(k, r)
     log.debug(
         Template("*************$res*************").substitute(res=res))
     try:
         if not re.match(v, res):
             info += "响应结果使用正则表达式匹配失败,请检查,"
     except Exception as e:
         info += Template("响应结果使用正则表达式匹配异常,异常信息:$e").substitute(e=e)
     return info
Ejemplo n.º 9
0
 def query(self, sql):
     with self.__conn.cursor() as cursor:
         log.info('query sql is: {}'.format(sql))
         try:
             cursor.execute(sql)
             # data_one = cursor.fetchone()
             data_all = cursor.fetchall()
             log.debug(Template('query results is: $all').substitute(all=data_all))
             return data_all
         except Exception as e:
             log.error('query fail, error info: {}, the sql is: {}'.format(str(e), str(sql)))
             return False
Ejemplo n.º 10
0
 def _secret(cls):
     timestamp = str(round(time.time() * 1000))
     secret = settings.dingrobot_secret
     secret_enc = secret.encode('utf-8')
     string_to_sign = '{}\n{}'.format(timestamp, secret)
     string_to_sign_enc = string_to_sign.encode('utf-8')
     hmac_code = hmac.new(secret_enc,
                          string_to_sign_enc,
                          digestmod=hashlib.sha256).digest()
     sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
     log.debug('dingrobot secret timestamp is: {}, sign is: {}'.format(
         timestamp, sign))
     return timestamp, sign
Ejemplo n.º 11
0
    def _read_file(self):
        """
        读取Excel文件,解析基础配置sheet,数据初始化sheet, 数据恢复sheet, 公共方法sheet和所有测试套sheet
        :return:
        """
        all_sheets = {}
        test_suite = []
        try:
            workbook = xlrd.open_workbook(self.filepath)

        except Exception as e:
            log.exception(
                string.Template("open testcase file fail, please check! %e").
                substitute(e=e))
            return False

        sheet_names = workbook.sheet_names()
        log.debug(
            string.Template("testcase sheets: $sheet_names").substitute(
                sheet_names=sheet_names))
        # print(sheet_names)

        if '基础配置' in sheet_names:
            base_configs = workbook.sheet_by_name('基础配置')
            all_sheets['base_configs'] = base_configs
            sheet_names.remove('基础配置')
        if '数据初始化' in sheet_names:
            initialize_datas = workbook.sheet_by_name('数据初始化')
            all_sheets['initialize_datas'] = initialize_datas
            sheet_names.remove('数据初始化')
        if '数据恢复' in sheet_names:
            restore = workbook.sheet_by_name('数据恢复')
            all_sheets['restore'] = restore
            sheet_names.remove('数据恢复')
        if '公共方法' in sheet_names:
            common_func = workbook.sheet_by_name('公共方法')
            all_sheets['common_func'] = common_func
            sheet_names.remove('公共方法')
        if '全局变量' in sheet_names:
            global_vars = workbook.sheet_by_name('全局变量')
            all_sheets['global_vars'] = global_vars
            sheet_names.remove('全局变量')
        for sheet in sheet_names:
            test_suite.append(workbook.sheet_by_name(sheet))
        log.info(
            string.Template(
                "All the test suite that need to be tested: $test_suite").
            substitute(test_suite=test_suite))
        all_sheets['testsuites'] = test_suite

        return all_sheets
Ejemplo n.º 12
0
def check_response_text(fields, response):
    error_info = ""
    log.debug(
        Template("fields: $fields, response: $response").substitute(
            fields=fields, response=response))
    if not fields:
        return error_info
    if isinstance(fields, str):
        log.debug('is a string fields, value is:'.format(fields))
        fs = fields.split(',')
    elif isinstance(fields, list):
        log.debug('is a list fields, value is: '.format(str(fields)))
        fs = fields
    else:
        log.error('fields param type error')
        return 'check res_text error, fields param type error'
    for text in fs:
        text = text.lstrip("'").lstrip('"').rstrip("'").rstrip('"')
        if text:
            log.debug(Template("待校验的内容: $text").substitute(text=text))
            if isinstance(response, dict):
                isempty = jmespath.search(text, response)
                if isempty is None:
                    error_info += Template(
                        "接口响应内容没有待校验的字段:$t,响应内容:$res").substitute(t=text,
                                                                  res=response)
            else:
                if text not in response:
                    error_info += Template(
                        "接口响应内容没有待校验的字段:$t,响应内容:$res").substitute(t=text,
                                                                  res=response)

    return error_info
Ejemplo n.º 13
0
    def send(self,
             mail_body,
             receivers,
             attachs=None,
             subject="auto-test mail notify"):
        """
        func: 发送邮件功能
        :param mail_body: 邮件文本主体,字符串类型
        :param receivers: 接收者列表,list类型
        :param attachs: 需要添加的附件,list类型,list中的每个元素需要是dict类型,并且需要有filename和filepath两个属性
        :param subject: 邮件主题
        :return:
        """
        if not attachs:
            if not isinstance(attachs, list):
                log.error('attach param is not a list')
                attach = None
        msg = MIMEMultipart()  # 支持邮件中附带附件
        msg['Subject'] = Header(subject, 'utf-8')
        msg['From'] = Header(self.sender, 'utf-8')
        for receiver in receivers:
            msg['To'] = Header(receiver, 'utf-8')

        mail_body = "(本邮件是程序自动下发的,请勿回复!)\r\n" + mail_body
        text_content = MIMEText(mail_body, 'plain', 'utf-8')
        msg.attach(text_content)
        # 添加附件
        if attachs:
            attachs = self.attach_check(attachs)
            for att in attachs:
                filepath = att.get('filepath')
                filename = att.get('filename')
                log.debug('filepath is: {}'.format(filepath))
                att_tmp = MIMEText(
                    open(filepath, 'rb').read(), 'base64', 'utf-8')
                att_tmp['Content-type'] = 'application/octet-stream'
                att_tmp[
                    'Content-Disposition'] = 'attachment; filename="{}"'.format(
                        filename)
                msg.attach(att_tmp)
        try:
            if self.smtp_link():
                self.smtp_handler.sendmail(self.sender, receivers,
                                           msg.as_string())
                log.info("send mail success!")

        except Exception as e:
            log.error("发送邮件异常, 错误信息:{}".format(e))
Ejemplo n.º 14
0
 def open_report_server(self, report_dir, ip=None, port=None):
     if not port:
         port = 55555
     suffix_dir = os.path.split(report_dir)[0]
     relative_path = os.path.split(report_dir)[1]
     self.trend_detail(report_dir)
     os.chdir(suffix_dir)
     self.check_port_is_open(port)
     generate_cmd = "allure generate {} -o {} -c".format(
         relative_path, self.allure_report)
     if ip:
         open_server_cmd = "allure open {} -h {} -p {}".format(
             self.allure_report, ip, port)
     else:
         open_server_cmd = "allure open {} -p {}".format(
             self.allure_report, port)
     obj = subprocess.Popen(generate_cmd, shell=True)
     obj.communicate()
     obj = subprocess.Popen(open_server_cmd,
                            shell=True,
                            stdout=subprocess.PIPE,
                            stdin=subprocess.PIPE,
                            stderr=subprocess.PIPE)
     couter = 0
     for item in iter(obj.stdout.readline, 'b'):
         couter += 1
         encode_type = chardet.detect(item)
         if encode_type['encoding'] == 'utf-8':
             item = item.decode('utf-8')
         elif encode_type['encoding'] == 'Windows-1252':
             item = item.decode('Window-1252')
         else:
             pass
         log.debug('subprocess out is: {}'.format(str(item)))
         pattern = re.compile(r'Server started at <(.+?)>\.')
         rs = re.search(pattern, str(item))
         if rs:
             url = rs.group(1)
             log.info('reports server is: {}'.format(url))
             return url
         time.sleep(0.5)
         if couter > 100:
             return "获取allure报告服务地址失败"
Ejemplo n.º 15
0
 def _file_parse(self, file):
     with open(file, 'r', encoding='utf-8') as f:
         content = f.read()
     try:
         json_conten = json.loads(content)
         log.debug(
             Template("转换为json格式后的api信息:$api").substitute(api=json_conten))
         log.debug(type(json_conten))
     except Exception as e:
         print("调试文件格式不符合json格式,解析出错,请检查!错误信息: {}".format(str(e)))
         log.error(
             Template("调试文件格式不符合json格式,解析出错,请检查!错误信息: $e").substitute(e=e))
         sys.exit(-1)
     if isinstance(json_conten, dict):
         if not json_conten.get("url") and not json_conten.get('method'):
             print("调试用例没有url信息或没有method信息")
             log.error(Template("调试用例没有url信息或没有method信息").substitute())
             raise Exception('调试用例没有url信息或没有method信息')
         self.api_infos = [json_conten]
     elif isinstance(json_conten, list):
         for api in json_conten:
             if not api.get("url") and not api.get('method'):
                 print(
                     Template("$api调试用例没有url信息或没有method信息").substitute(
                         api=api))
                 log.error(
                     Template("$api调试用例没有url信息或没有method信息").substitute(
                         api=api))
                 raise Exception(
                     Template("$api调试用例没有url信息或没有method信息").substitute(
                         api=api))
         self.api_infos = json_conten
     else:
         print(
             Template("调试文件格式不符合json格式,解析结果异常,请检查!解析后的结果:$r").substitute(
                 r=json_conten))
         log.error(
             Template("调试文件格式不符合json格式,解析结果异常,请检查!解析后的结果:$r").substitute(
                 r=json_conten))
         raise Exception(
             Template('调试文件格式不符合json格式,解析结果异常,请检查!解析后的结果:$r').substitute(
                 r=json_conten))
     return json_conten
Ejemplo n.º 16
0
 def kill_process_by_port_on_win(cls, port):
     find_cmd = 'netstat -aon|findstr "{}"'.format(port)
     kill_cmd = "taskkill -pid {} -f"
     with os.popen(find_cmd) as res:
         res = res.read().split('\n')
     for line in res:
         temp = [i for i in line.split(' ') if i != '']
         log.debug('the netstat info is: {}'.format(temp))
         if len(temp) > 4:
             addr = temp[1]
             if str(addr.split(':')[1]) == str(port):
                 pid = temp[4]
                 log.info(
                     'find the port, the corresponding PID is: {}, and kill the PID process'
                     .format(pid))
                 os.system(kill_cmd.format(pid))
                 return
     log.info('No corresponding port process was found')
     return
Ejemplo n.º 17
0
def check_response_header(fields, headers):
    error_info = ""
    if not fields:
        return error_info
    log.debug(
        Template("fields: $fields, headers: $headers").substitute(
            fields=fields, headers=headers))
    if not fields:
        return error_info
    if not isinstance(fields, str):
        log.debug(type(fields))
        log.debug(fields)
        raise TypeError("neet to check fields is not a str")
    for text in fields.split(','):
        text = text.lstrip("'").lstrip('"').rstrip("'").rstrip('"')
        if isinstance(headers, dict):
            # if not headers.get(text):
            isempty = jmespath.search(text, headers)
            if isempty is None:
                error_info += Template(
                    "接口响应内容没有待校验的字段:$t,响应内容:$res").substitute(t=text,
                                                              res=headers)
        else:
            if text not in headers:
                error_info += Template(
                    "接口响应内容没有待校验的字段:$t,响应内容:$res").substitute(t=text,
                                                              res=headers)

    return error_info
Ejemplo n.º 18
0
def check_response_header(fields, headers):
    error_info = ""
    if not fields:
        return error_info
    log.debug(
        Template("fields: $fields, headers: $headers").substitute(
            fields=fields, headers=headers))
    if not fields:
        return error_info
    if isinstance(fields, str):
        log.debug('is a string fields, value is:'.format(fields))
        fs = fields.split(',')
    elif isinstance(fields, list):
        log.debug('is a list fields, value is: '.format(str(fields)))
        fs = fields
    else:
        log.error('fields param type error')
        raise TypeError('fields param type error')
    for text in fs:
        text = text.lstrip("'").lstrip('"').rstrip("'").rstrip('"')
        if text:
            if isinstance(headers, dict):
                # if not headers.get(text):
                isempty = jmespath.search(text, headers)
                if isempty is None:
                    error_info += Template(
                        "接口响应内容没有待校验的字段:$t,响应内容:$res").substitute(t=text,
                                                                  res=headers)
            else:
                if text not in headers:
                    error_info += Template(
                        "接口响应内容没有待校验的字段:$t,响应内容:$res").substitute(t=text,
                                                                  res=headers)

    return error_info
Ejemplo n.º 19
0
    def api_request(self):
        api_infos = self.api_infos
        # log.debug(Template("api_infos: $api").substitute(api=api_infos))
        index = 0
        for api_info in api_infos:
            index += 1
            try:
                log.debug("正在执行用例:{}".format(index))
                res = ApiHandler(api_info).api_request()
            except Exception as e:
                log.error(
                    Template("用例$i 请求异常,异常信息:$e,用例信息:$api").substitute(
                        i=index, e=e, api=api_info))
                continue
            try:
                res_json = res.json()
            except Exception as e:
                log.error(
                    Template("用例$i 响应结果解析为json格式异常,响应信息:$t,异常信息:$e,用例信息:"
                             "$api").substitute(t=res.text, e=e, api=api_info))
                continue
            flag = True
            if api_info.get("verify_fields"):
                msg = eut.check_verify_fields(api_info["verify_fields"],
                                              res_json)
                if msg:
                    log.error(Template("字段校验失败,失败信息:$msg").substitute(msg=msg))
                    flag = False
                    # check.equal(1, 2, msg=msg)
                else:
                    log.info(Template("字段校验成功").substitute())

            if api_info.get("res_text"):
                msg = eut.check_response_text(api_info['res_text'], res_json)
                if msg:
                    log.error(
                        Template("响应内容校验失败,失败信息:$msg").substitute(msg=msg))
                    flag = False
                    # check.equal(1, 2, msg=msg)
                else:
                    log.info(Template("响应内容校验成功").substitute())

            if api_info.get("res_header"):
                msg = eut.check_response_header(api_info['res_header'],
                                                res.headers)
                if msg:
                    log.error(
                        Template("响应头校验失败,失败信息:$msg").substitute(msg=msg))
                    flag = False
                    # check.equal(1, 2, msg=msg)
                else:
                    log.info(Template("响应头校验成功").substitute())

            if api_info.get("status_code"):
                msg = eut.check_status_code(api_info['status_code'],
                                            res.status_code)
                if msg:
                    log.error(
                        Template("响应状态码校验失败,失败信息:$msg").substitute(msg=msg))
                    flag = False
                    # check.equal(1, 2, msg=msg)
                else:
                    log.info(Template("响应状态码校验成功").substitute())

            if api_info.get("res_time"):
                msg = eut.check_response_time(api_info['res_time'],
                                              res.elapsed.total_seconds())
                if msg:
                    log.error(
                        Template("响应时间校验失败,失败信息:$msg").substitute(msg=msg))
                    flag = False
                    # check.equal(1, 2, msg=msg)
                else:
                    log.info(Template("响应时间校验成功").substitute())

            if api_info.get("expression"):
                msg = eut.check_pyexpression(api_info['expression'], res_json)
                if msg:
                    log.error(
                        Template("py表达式校验失败,失败信息:$msg").substitute(msg=msg))
                    flag = False
                    # check.equal(1, 2, msg=msg)
                else:
                    log.info(Template("py表达式校验成功").substitute())

            if not flag:
                log.info(
                    Template("用例$i 执行失败,用例信息:$api").substitute(i=index,
                                                               api=api_info))
Ejemplo n.º 20
0
        random_front = generate_random_str()
        random_back = generate_random_str()
        try:
            content = json.dumps(case, ensure_ascii=False)
        except Exception as e:
            log.error(
                string.Template("testcase json dumps fail, error info: $e").
                substitute(e=e))
            raise VarReplaceException
        content = re.sub(pattern_front, random_front, content)
        content = re.sub(pattern_back, random_back, content)
        # log.debug(string.Template("after replaced random string: $content").substitute(content=content))
        pattern = re.compile(r"\{\w+\}")
        key_words = re.findall(pattern, content)
        log.debug(
            string.Template("所有需要进行变量替换的变量为: $key_words").substitute(
                key_words=key_words))

        if key_words:
            """
            循环遍历所有待替换的字符,如果待替换的字符在传入的对象列表中有对应的属性,则进行替换
            否则不作处理
            对象替换按传入的对象的下标进行排序,匹配到了之后,退出循环,即取最先匹配到的对象的属性值
            """
            for key_word in key_words:
                real_word = key_word.lstrip('{').rstrip('}')
                for index in range(0, len(object_list)):
                    log.debug(
                        Template("$o对象的interface_vars属性$a").substitute(
                            o=object_list[index].__class__.__name__,
                            a=object_list[index].__dict__.get(
Ejemplo n.º 21
0
        random_front = generate_random_str()
        random_back = generate_random_str()
        try:
            content = json.dumps(case, ensure_ascii=False)
        except Exception as e:
            log.error(
                string.Template("testcase json dumps fail, error info: $e").
                substitute(e=e))
            raise VarReplaceException
        content = re.sub(pattern_front, random_front, content)
        content = re.sub(pattern_back, random_back, content)
        # log.debug(string.Template("after replaced random string: $content").substitute(content=content))
        pattern = re.compile(r"\{\w+\}")
        key_words = re.findall(pattern, content)
        log.debug(
            string.Template("所有需要进行变量替换的变量为: $key_words").substitute(
                key_words=key_words))

        if key_words:
            """
            循环遍历所有待替换的字符,如果待替换的字符在传入的对象列表中有对应的属性,则进行替换
            否则不作处理
            对象替换按传入的对象的下标进行排序,匹配到了之后,退出循环,即取最先匹配到的对象的属性值
            """
            for key_word in key_words:
                real_word = key_word.lstrip('{').rstrip('}')
                for index in range(0, len(object_list)):
                    log.debug(
                        Template("$o对象的所有属性$a").substitute(
                            o=object_list[index].__class__.__name__,
                            a=object_list[index].__dict__))