FastApi(二)

响应模型:

from fastapi import FastAPI, status

from typing import Optional
from pydantic import BaseModel

import uvicorn

app = FastAPI()

"""
    在任意的路径操作中使用 response_model 参数来声明用于响应的模型
    @app.get()  @app.post() @app.put() @app.delete()等
    
    仅返回显式设定的值:
    response_model_exclude_unset=True
    response_model_exclude_defaults=True
    response_model_exclude_none=True 
    
    省略某些属性:
    response_model_include
    response_model_exclude 
    接收一个由属性名称 str 组成的 set 来包含(忽略其他的)或者排除(包含其他的)这些属性     
"""

class UserBase(BaseModel):
    username: str
    email: str
    full_name: Optional[str] = None

class UserIn(UserBase):
    password: str

class UserOut(UserBase):
    pass

class UserInDB(UserBase):
    hashed_password: str

def fake_password_hasher(raw_password: str):
    return "supersecret" + raw_password

def fake_save_user(user_in: UserIn):
    hashed_password = fake_password_hasher(user_in.password)
    user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password)
    print("User saved! ..not really")
    return user_in_db

@app.post("/user/", response_model=UserOut)
async def create_user(user_in: UserIn):
    user_saved = fake_save_user(user_in)
    return user_saved

@app.post("/casedata/", status_code=status.HTTP_201_CREATED)   #post入参也可以没有BaseModel类型
async def create_item(casedata: str):
    return {"casedata": casedata}

if __name__ == '__main__':
    uvicorn.run('pNewOrder:app', host='0.0.0.0', port=8001, reload=True, debug=True, workers=1)  #app即fastapi实例的名称

实战:

from template.BaseCode import BaseCode
from string import Template
from datetime import datetime
import time
import os

from Util.Log import Logger
from configuration.BaseConfig import productfunc
from configuration.ConstantConfig import testscriptdir
from fastapi import FastAPI, HTTPException, Body
import uvicorn

app = FastAPI()


class DDS(BaseCode):

    def __init__(self, casedata, testscriptdir):
        """
        初始化
        :param casedata: 从数据库解析重组的数据
        :param testscriptdir:  生成php脚本存放的路径
        """
        self.casedata = casedata
        self.testscriptdir = testscriptdir
        self.interface_name = self.__get_interface_name()
        self.mylogger = Logger(self.interface_name, self.interface_name).getlog()

    def __get_interface_name(self):
        if "test_interface" in self.casedata.keys() and self.casedata['test_interface']:
            if "interface_name" in self.casedata['test_interface'][0].keys():
                interface_name = self.casedata['test_interface'][0]['interface_name']
        return interface_name

    def __get_current_date(self):
        d = datetime.now().strftime("%Y-%m-%d")
        return d

    def __get_current_time(self):
        t = datetime.now().strftime("%H:%M:%S")
        return t

    def __get_product_func(self, product_dict=productfunc):
        if "product_func" in self.casedata.keys() and self.casedata['product_func']:
            if self.casedata['product_func'] in product_dict.values():
                return self.casedata['product_func']

        return "getProductSceneFastNormal"  # 兜底返回

    def head_fix(self, head_fix=HEAD_FIX):
        """
        开头固定部分替换
        :param head_fix:
        :return:
        """
        try:
            if 'case_set' in self.casedata.keys() and self.casedata['case_set']:
                pass
            else:
                self.mylogger.info('Error: 每个case必须在开头注释中注明Case set')

            if 'AbsolutePath' in self.casedata.keys() and self.casedata['AbsolutePath']:
                pass
            else:
                self.mylogger.info('File not find error : flow.php')
        except Exception as e:
            raise e

        d = {"case_set": self.casedata['case_set'], "AbsolutePath": self.casedata['AbsolutePath'],
             "Date": self.__get_current_date(), "Time": self.__get_current_time()}
        code = Template(head_fix)
        head_fix_result = code.safe_substitute(d)
        return head_fix_result

    def product_func(self, product=PRODUCT):
        p = self.__get_product_func()
        code = Template(product)
        product_fix = code.safe_substitute(product_func=p)
        return product_fix

    def single_interface_create(self, dada_dict, base_code=BASE_CODE):
        """
        定义单接口代码生成,以便set_up及test_case调用,d增加灵活性
        :return:
        """
        if not isinstance(dada_dict, dict):
            raise TypeError('类型错误')

        code = Template(base_code)
        single_dict = self.convert_multi_dict(dada_dict)
        base_code_result = code.safe_substitute(single_dict)
        return base_code_result

    def multi_interface_create(self, data_list, base_code=BASE_CODE):
        """
        定义多接口代码生成
        :param data_list:
        :param base_code:
        :return:
        """
        if not isinstance(data_list, list):
            raise TypeError('类型错误')

        if len(data_list) == 0:
            raise ValueError("空列表")

        set_up_string = ""
        if len(data_list) == 1:
            if isinstance(data_list[0], dict):
                set_up_string += self.single_interface_create(self.convert_multi_dict(data_list[0]))
                return set_up_string
            else:
                raise TypeError('类型错误')
        elif len(data_list) > 1:
            for i in range(len(data_list)):
                if not isinstance(data_list[i], dict):
                    break
                else:
                    set_up_string += self.single_interface_create(self.convert_multi_dict(data_list[i]))
            return set_up_string

    def convert_dict_to_php_array(self, interface_params):
        """
        {"a":1,"b":2}转换为php的关联数组['a'=>1, 'b'=>2]
        :param interface_params:
        :return:
        """
        convert_result = str(interface_params).replace(":", "=>").replace("{", "[").replace("}", "]")
        return convert_result

    def convert_multi_dict(self, multi_dict):
        """
        两层嵌套转一层{'a':1, 'b':{'errno':0, 'message':'success'}}转为{'a':1, 'b_errno':0, 'b_message':'success'}
        :return:
        """
        result = {}
        for x in multi_dict.keys():
            if type(multi_dict[x]) is dict:
                for i in multi_dict[x].keys():
                    key = x + "_" + i
                    result[key] = multi_dict[x][i]
            else:
                result[x] = multi_dict[x]
        return result

    def set_up_improve(self):
        """
        前置依赖,单个接口/多个接口
        :return:
        """
        if 'set_up' in self.casedata.keys() and self.casedata['set_up']:
            set_up_lists = self.casedata['set_up']
            return self.multi_interface_create(set_up_lists)
        else:
            return None

    def check_test_interface_params_single(self, test_interface):
        """
        module_name,interface_name,response校验,interface_params转为php关联数组,response去掉嵌套
        :param test_interface:
        :return:
        """

        if not isinstance(test_interface, dict):
            raise TypeError('类型错误')

        if "module_name" not in test_interface.keys() or "interface_name" not in test_interface.keys():
            raise ValueError('被测接口缺少必要参数module_name或interface_name')
        if not test_interface["module_name"] or not test_interface["interface_name"]:
            raise ValueError('被测接口必要参数module_name或interface_name不能为空')

        if 'interface_params' in test_interface.keys() and test_interface['interface_params']:
            if isinstance(test_interface['interface_params'], dict):
                test_interface['interface_params'] = self.convert_dict_to_php_array(test_interface['interface_params'])
        else:
            test_interface['interface_params'] = []

        if 'response' in test_interface.keys() and test_interface['response']:
            pass
        else:
            raise ValueError('请填写校验点')

        new_test_interface = self.convert_multi_dict(test_interface)
        return new_test_interface

    def check_test_interface_params_multi(self, test_interface_list):
        """
        检查多列表,列表嵌套字典
        :param test_interface_list:
        :return:
        """
        if not isinstance(test_interface_list, list):
            raise TypeError('类型错误')

        if len(test_interface_list) == 0:
            raise ValueError('列表为空')

        test_interface_param = []
        if len(test_interface_list) == 1:
            if isinstance(test_interface_list[0], dict):
                return self.check_test_interface_params_single(test_interface_list[0])
            else:
                raise TypeError('类型错误')
        elif len(test_interface_list) > 1:
            for i in range(len(test_interface_list)):
                if not isinstance(test_interface_list[i], dict):
                    break
                else:
                    test_interface_param.append(self.check_test_interface_params_single(test_interface_list[i]))
            return test_interface_param

    def test_case(self):
        """
        单个/多个测试接口的情况
        :return:
        """
        try:
            if 'test_interface' in self.casedata.keys() and self.casedata['test_interface']:
                interfaces = self.casedata['test_interface']
                if len(interfaces) == 1:
                    params = self.check_test_interface_params_single(interfaces[0])
                    return self.single_interface_create(self.convert_multi_dict(params))
                elif len(interfaces) >= 1:
                    params = self.check_test_interface_params_multi(interfaces)
                    return self.multi_interface_create(params)
            else:
                self.mylogger.info('Error: 没有被测接口')
        except Exception as e:
            raise e

    def tear_down(self):
        """
        数据清洗
        :return:
        """
        pass
        return ""

    def data_assert(self):
        if 'assert_rule' in self.casedata.keys() and self.casedata['assert_rule']:
            pass


    def end_fix(self, end_fix=END_FIX):
        """
        返回固定的。。。。
        :param end_fix:
        :return:
        """
        return end_fix


    def run_main(self):
        head_fix = self.head_fix()
        if 'product_func' in self.casedata.keys() and self.casedata['product_func']:
            product = self.product_func()
        else:
            product = 'getProductSceneFastNormal'
        if 'set_up' in self.casedata.keys() and self.casedata['set_up']:
            set_up = self.set_up_improve()
        else:
            set_up = []
        test_case = self.test_case()
        tear_down = self.tear_down()
        end_fix = self.end_fix()
        result = head_fix + product + os.linesep + set_up + test_case + tear_down + end_fix
        return result

    def create_file(self):
        current_time = time.strftime("%Y-%m-%d_%H_%M_%S")
        file_path = testscriptdir + r"/" + 'Auto_' + self.__get_interface_name() + "_" + current_time + ".php"
        message = self.run_main()
        with open(file_path, 'w') as f:
            f.write(message)

    def update_status(self, status):
        """
        先在report中查找,判断是成功还是失败,都没有则在脚本中查找
        :param status:
        :return:
        """
        pass

    def update_case_name(self, case_name):
        """
        更新数据库中自动化case的名称
        :return:
        """
        pass

    def update_operator(self, operator):
        """
        需获取当前登录的用户
        :return:
        """
        pass
        self.operator = operator
        return self.operator

    def deduplication_interface(self, interface_list):
        """
        判断列表中是否有重复元素
        :param interface_list:
        :return:
        """
        if not isinstance(interface_list, list):
            raise TypeError('类型不匹配')

        if len(interface_list) <=1:
            return False
        elif len(interface_list) > 1:
            interface_list_new = set(interface_list)
            if len(interface_list_new) == len(interface_list):
                return False
            else:
                return True

    def get_interface_name_list(self, interface_list):
        """
        获取set_up或test_interface中所有interface_name的值
        :param interface_list: 列表嵌套字典
        :return:
        """
        if not isinstance(interface_list, list):
            raise TypeError('类型不匹配')

        if len(interface_list) == 0:
            return []

        get_interface_name_list = []
        if len(interface_list) == 1:
            if "interface_name" in interface_list[0].keys():
                return interface_list[0]["interface_name"]
        elif len(interface_list) > 1:
            for i in range(len(interface_list)):
                if not isinstance(interface_list[i], dict):
                    break
                elif "interface_name" in interface_list[i].keys():
                    name = interface_list[i]["interface_name"]
                    get_interface_name_list.append(name)
            return get_interface_name_list

    def is_set_up_interface_repeat(self):
        interface_name = self.casedata["set_up"]
        set_up_interface_name = self.get_interface_name_list(interface_name)
        if self.deduplication_interface(set_up_interface_name):
            raise ValueError('set_up 接口重复, 请检查')

    def is_test_interface_repeat(self):
        interface_name = self.casedata["test_interface"]
        set_up_interface_name = self.get_interface_name_list(interface_name)
        if self.deduplication_interface(set_up_interface_name):
            raise ValueError('test_interface 接口重复, 请检查')


@app.post('/woody/dws/')
async def auto_create_dws_file(casedata: dict = Body(..., title='woody-transformer', description='自动化入参',example=''):

    if "case_set" not in casedata.keys():
        raise HTTPException(status_code=404, detail='每个case必须在开头注释中注明Case set')

    if "AbsolutePath" not in casedata.keys():
        raise HTTPException(status_code=405, detail='找不到flow.php文件')

    if "set_up" not in casedata.keys():
        raise HTTPException(status_code=302, detail='没有前置依赖')

    d = DWS(casedata, testscriptdir)
    result5 = d.run_main()
    return {"result5": result5}

if __name__ == '__main__':
    uvicorn.run('DWS:app', host='0.0.0.0', port=8090, reload=True, debug=True, workers=1)  # app即fastapi实例的名称

结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值