From a96d674518b56ecdcb9df4cd740e603f1c6d4b08 Mon Sep 17 00:00:00 2001 From: floraachy <1622042529@qq.com> Date: Wed, 28 Jun 2023 16:54:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=8A=A8=E6=80=81=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=9A=84=E7=83=AD=E5=8A=A0=E8=BD=BD=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E5=B0=86=E6=95=B0=E6=8D=AE=E6=8F=90=E5=8F=96?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E5=8D=95=E7=8B=AC=E6=8B=8E=E5=87=BA=E6=9D=A5?= =?UTF-8?q?=E5=8F=98=E6=88=90=E5=8D=95=E7=8B=AC=E7=9A=84=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- case_utils/data_handle.py | 214 +++++++++++++++++------- case_utils/extract_data_handle.py | 64 +++++++ data/gitlink/test_new_project_demo.yaml | 66 +++++++- 3 files changed, 279 insertions(+), 65 deletions(-) create mode 100644 case_utils/extract_data_handle.py diff --git a/case_utils/data_handle.py b/case_utils/data_handle.py index 4f724e3..92fc847 100644 --- a/case_utils/data_handle.py +++ b/case_utils/data_handle.py @@ -6,13 +6,146 @@ # @Software: PyCharm # @Desc: 数据处理 +# 标准库导入 +import random import re -from string import Template -from jsonpath import jsonpath -from loguru import logger +from datetime import datetime, date, timedelta +# 第三方库导入 from faker import Faker +from string import Template -faker = Faker() + +class FakerData: + """ + 测试数据生成类 + """ + + def __init__(self): + self.fk_zh = Faker(locale='zh_CN') + self.faker = Faker() + + @classmethod + def generate_random_int(cls, *args) -> int: + """ + :return: 随机数 + """ + # 检查是否传入了参数 + if not args: + # 没有传参,就从5000内随机取一个整数返回 + return random.randint(0, 5000) + + # 排序参数并获取最小值和最大值 + min_val = min(args) + max_val = max(args) + + # 生成并返回随机整数 + return random.randint(min_val, max_val) + + def generate_phone(self, lan="en") -> int: + """ + :return: 随机生成手机号码 + """ + if lan == "zh": + phone = self.fk_zh.phone_number() + else: + phone = self.faker.phone_number() + return phone + + def generate_id_number(self, lan="en") -> int: + """ + + :return: 随机生成身份证号码 + """ + if lan == "zh": + id_number = self.fk_zh.ssn() + else: + id_number = self.faker.ssn() + return id_number + + def generate_female_name(self, lan="en") -> str: + """ + + :return: 女生姓名 + """ + if lan == "zh": + female_name = self.fk_zh.name_female() + else: + female_name = self.faker.name_female() + return female_name + + def generate_male_name(self, lan="en") -> str: + """ + + :return: 男生姓名 + """ + if lan == "zh": + male_name = self.fk_zh.name_male() + else: + male_name = self.faker.name_male() + return male_name + + def generate_name(self, lan="en") -> str: + """ + + :return: 人名 + """ + if lan == "zh": + name = self.fk_zh.name() + else: + name = self.faker.name() + return name + + def generate_email(self, lan="en") -> str: + """ + + :return: 生成邮箱 + """ + if lan == "zh": + email = self.fk_zh.email() + else: + email = self.faker.email() + return email + + def generate_identifier(self, lan="en"): + """ + :return:生成随机标识,满足要求:长度为2~100, 只能包含数字,字母,下划线(_),中划线(-),英文句号(.),必须以数字和字母开头,不能以下划线/中划线/英文句号开头和结尾 + """ + if lan == "zh": + fk = self.fk_zh + else: + fk = self.faker + while True: + identifier = fk.slug() # 生成随机的slug标识 + + if ( + re.match(r'^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,98}[a-zA-Z0-9]$', identifier) and + not (identifier.startswith('_') or identifier.startswith('-') or identifier.startswith('.')) and + not (identifier.endswith('_') or identifier.endswith('.')) + ): + return identifier + + @classmethod + def generate_time(cls, fmt='%Y-%m-%d %H:%M:%S') -> str: + """ + 计算当前时间 + :return: + """ + now_time = datetime.now().strftime(fmt) + return now_time + + @classmethod + def generate_today_date(cls): + """获取今日0点整时间""" + + _today = date.today().strftime("%Y-%m-%d") + " 00:00:00" + return str(_today) + + @classmethod + def generate_time_after_week(cls): + """获取一周后12点整的时间""" + + _time_after_week = (date.today() + timedelta(days=+6)).strftime("%Y-%m-%d") + " 00:00:00" + return _time_after_week def data_handle(obj, source): @@ -25,7 +158,26 @@ def data_handle(obj, source): obj = Template(obj).safe_substitute(source) # 寻找${python表达式}, 将Python表达式eval得出其具体值 for func in re.findall('\\${(.*?)}', obj): - obj = obj.replace('${%s}' % func, eval_data_process(func)) + """ + 兼容一下如下数据处理:faker.name().replace(" ", "").replace(".", "") + faker是FakerData()中的实例变量。 + """ + if func.startswith("faker."): + # 英文的faker数据:self.faker = Faker() + faker = FakerData().faker + obj = obj.replace('${%s}' % func, eval(func)) + elif func.startswith("fk_zh."): + # 中文的faker数据: self.fk_zh = Faker(locale='zh_CN') + fk_zh = FakerData().fk_zh + obj = obj.replace('${%s}' % func, eval(func)) + else: + # 这里获取到的func是这样的格式,例如random_int(), 但实际我们通过FakerData()获取到的方法是这样的格式,例如random_int, 所以我们需要进行处理 + func_name = func.split("(")[0] if "(" in func else func + if hasattr(FakerData(), func_name) and callable(getattr(FakerData(), func_name)): + # 调用FakerData类的方法获取数据 + obj = obj.replace('${%s}' % func, str(getattr(FakerData(), func_name)())) + # 处理其他Python表达式,例如:${1+1} + obj = obj.replace('${%s}' % func, func) obj = eval_data_process(obj) return obj return eval_data_process(obj) @@ -73,55 +225,3 @@ def eval_data_process(data): for key, value in data.items(): data[key] = eval_data_process(eval_data(value)) return data - - -def json_extractor(obj: dict, expr: str = '.'): - """ - :param obj :json/dict类型数据 - :param expr: 表达式, . 提取字典所有内容, $.test_api_case 提取一级字典case, $.test_api_case.data 提取case字典下的data - :return result: 提取的结果,未提取到返回 None - """ - try: - result = jsonpath(obj, expr)[0] - logger.debug("\n======================================================\n" \ - "-------------Start:json_extractor--------------------\n" - f"提取表达式为: {expr} \n" - f"提取值为: {result}\n" - "=====================================================") - print("提取响应内容成功,提取表达式为: {} 提取值为 {}".format(expr, result)) - except Exception as e: - logger.debug("\n======================================================\n" \ - "-------------End:json_extractor--------------------\n" - f"提取表达式为: {expr}\n" - f"提取数据为: {obj}\n" - f"错误信息为:{e}\n" - "=====================================================") - print(f'未提取到内容,请检查表达式是否错误!提取表达式为:{expr} 提取数据为 {obj}, 错误信息为:{e}') - result = None - return result - - -def re_extract(obj: str, expr: str = '.'): - """ - :param obj : 字符串数据 - :param expr: 正则表达式 - :return result: 提取的结果,未提取到返回 None - """ - try: - result = re.findall(expr, obj)[0] - logger.debug("\n======================================================\n" \ - "-------------Start:re_extract--------------------\n" - f"提取表达式为: {expr}\n" \ - f"提取值为: {result}\n" \ - "=====================================================") - print("提取响应内容成功,提取表达式为: {} 提取值为: {}".format(expr, result)) - except Exception as e: - logger.debug(f"\n======================================================\n" \ - "-------------End:re_extract--------------------\n" - f"提取表达式为: {expr}\n" \ - f"提取数据为: {obj}\n" \ - f"错误信息为:{e}\n" \ - "=====================================================") - print(f'未提取到内容,请检查表达式是否错误!提取表达式为:{expr} 提取数据为 {obj}, 错误信息为:{e}') - result = None - return result diff --git a/case_utils/extract_data_handle.py b/case_utils/extract_data_handle.py new file mode 100644 index 0000000..932bfd6 --- /dev/null +++ b/case_utils/extract_data_handle.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# @Time : 2023/6/28 14:35 +# @Author : chenyinhua +# @File : extract_data_handle.py +# @Software: PyCharm +# @Desc: 提取数据的一些方法 + +# 标准库导入 +import re +# 第三方库导入 +from jsonpath import jsonpath +from loguru import logger + + +def json_extractor(obj: dict, expr: str = '.'): + """ + :param obj :json/dict类型数据 + :param expr: 表达式, . 提取字典所有内容, $.test_api_case 提取一级字典case, $.test_api_case.data 提取case字典下的data + :return result: 提取的结果,未提取到返回 None + """ + try: + result = jsonpath(obj, expr)[0] + logger.debug("\n======================================================\n" \ + "-------------Start:json_extractor--------------------\n" + f"提取表达式为: {expr} \n" + f"提取值为: {result}\n" + "=====================================================") + print("提取响应内容成功,提取表达式为: {} 提取值为 {}".format(expr, result)) + except Exception as e: + logger.debug("\n======================================================\n" \ + "-------------End:json_extractor--------------------\n" + f"提取表达式为: {expr}\n" + f"提取数据为: {obj}\n" + f"错误信息为:{e}\n" + "=====================================================") + print(f'未提取到内容,请检查表达式是否错误!提取表达式为:{expr} 提取数据为 {obj}, 错误信息为:{e}') + result = None + return result + + +def re_extract(obj: str, expr: str = '.'): + """ + :param obj : 字符串数据 + :param expr: 正则表达式 + :return result: 提取的结果,未提取到返回 None + """ + try: + result = re.findall(expr, obj)[0] + logger.debug("\n======================================================\n" \ + "-------------Start:re_extract--------------------\n" + f"提取表达式为: {expr}\n" \ + f"提取值为: {result}\n" \ + "=====================================================") + print("提取响应内容成功,提取表达式为: {} 提取值为: {}".format(expr, result)) + except Exception as e: + logger.debug(f"\n======================================================\n" \ + "-------------End:re_extract--------------------\n" + f"提取表达式为: {expr}\n" \ + f"提取数据为: {obj}\n" \ + f"错误信息为:{e}\n" \ + "=====================================================") + print(f'未提取到内容,请检查表达式是否错误!提取表达式为:{expr} 提取数据为 {obj}, 错误信息为:{e}') + result = None + return result diff --git a/data/gitlink/test_new_project_demo.yaml b/data/gitlink/test_new_project_demo.yaml index 2922ab8..797adb1 100644 --- a/data/gitlink/test_new_project_demo.yaml +++ b/data/gitlink/test_new_project_demo.yaml @@ -18,8 +18,8 @@ case_new_project_demo_01: request_type: json payload: "user_id": ${user_id} - "name": ${faker.name().replace(" ", "").replace(".", "")} - "repository_name": ${faker.name().replace(" ", "").replace(".", "")} + "name": ${generate_name(len='zh')} + "repository_name": ${generate_identifier()} files: extract: project_id: $.id @@ -34,7 +34,7 @@ case_new_project_demo_01: case_new_project_demo_02: feature: 新建项目 title: 正确输入各项必填参数,新建项目成功(不校验数据库,单独传cookies) - run: False + run: True url: /api/projects.json method: POST headers: @@ -43,8 +43,8 @@ case_new_project_demo_02: request_type: json payload: "user_id": ${user_id} - "name": ${faker.name().replace(" ", "").replace(".", "")} - "repository_name": ${faker.name().replace(" ", "").replace(".", "")} + "name": ${generate_name(generate_name(len="zh"))} + "repository_name": ${generate_identifier()} files: extract: project_id: $.id @@ -67,8 +67,8 @@ case_new_project_demo_03: request_type: json payload: "user_id": ${user_id} - "name": ${faker.name().replace(" ", "").replace(".", "")} - "repository_name": ${faker.name().replace(" ", "").replace(".", "")} + "name": ${generate_name()} + "repository_name": ${generate_identifier()} files: extract: project_id: $.id @@ -83,4 +83,54 @@ case_new_project_demo_03: sql: select id,`name`, identifier from projects where user_id=${user_id} ORDER BY created_on DESC; $.id: ${project_id} $.name: ${project_name} - $.identifier: ${project_identifier} \ No newline at end of file + $.identifier: ${project_identifier} + +case_new_project_demo_04: + feature: 新建项目 + title: 正确输入各项必填参数,新建项目成功(04) + run: True + url: /api/projects.json + method: POST + headers: + Content-Type: application/json; charset=utf-8; + cookies: ${login_cookie} + request_type: json + payload: + "user_id": ${user_id} + "name": ${faker.name()} + "repository_name": ${generate_identifier()} + files: + extract: + project_id: $.id + project_name: $.name + project_identifier: $.identifier + assert_response: + eq: + http_code: 200 + $.login: ${login} + assert_sql: + +case_new_project_demo_05: + feature: 新建项目 + title: 正确输入各项必填参数,新建项目成功(05) + run: True + url: /api/projects.json + method: POST + headers: + Content-Type: application/json; charset=utf-8; + cookies: ${login_cookie} + request_type: json + payload: + "user_id": ${user_id} + "name": ${fk_zh.name()} + "repository_name": ${generate_identifier()} + files: + extract: + project_id: $.id + project_name: $.name + project_identifier: $.identifier + assert_response: + eq: + http_code: 200 + $.login: ${login} + assert_sql: \ No newline at end of file