ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

HttpRunner3源码阅读:2. 模型定义

2021-08-04 01:03:09  阅读:228  来源: 互联网

标签:定义 Union Text List HttpRunner3 源码 Dict BaseModel class


models.py

昨天体验的时候我们分别执行了httprunner -h,httprunner startproject demo, httprunner run demo,但是源码中其调用了其他文件中的方法所以暂时先不分析cli.py了,先从根本开始models.py

可用资料

typing[类型提示]: https://docs.python.org/zh-cn/3/library/typing.html
pydantic[类型校验]: https://pydantic-docs.helpmanual.io/
用上这两个库就有点强类型语言的味儿了
泛型: https://docs.python.org/zh-cn/3/library/typing.html#generics
枚举: https://docs.python.org/zh-cn/3/library/enum.html

导包分析

import os   # 系统包
from enum import Enum   # 枚举类
from typing import Any  # Any 表示 任意类型
from typing import Dict # dict 的泛型版本。
from typing import Text # Text 是 str 的别名
from typing import Union # 联合类型;Union[X, Y] 的意思是,非 X 即 Y
from typing import Callable # 可调类型; Callable[[int], str] 是把(int)转为 str 的函数。
from typing import List # list 的泛型版本。
from pydantic import BaseModel  # pydantic定义对象的基类
from pydantic import Field    # pydantic 中 字段扩展定义
from pydantic import HttpUrl  # 校验url地址的

类型别名定义

该系列中个人对类型的看法/叫法如下

  1. Text => str / 文本
  2. List => list / 列表
  3. Dict => dict / 字典
Name = Text     # Name 的本质 其实就是 Text(Text 本质又是 str)
Url = Text
BaseUrl = Union[HttpUrl, Text]  # 是url 或者 Text 两者之一
VariablesMapping = Dict[Text, Any] # key 是 Text ,value 是任意类型
FunctionsMapping = Dict[Text, Callable] # key 是 Text, value是可调用对象
Headers = Dict[Text, Text]  # key 是 str, value 也是 str
Cookies = Dict[Text, Text] # 同上
Verify = bool   # 布尔类型
Hooks = List[Union[Text, Dict[Text, Text]]] # 列表,列表中的元素是 str 或者 key,value 都是 str
Export = List[Text]  # 列表,列表中元素是 str
Validators = List[Dict] # 列表,列表中元素是 字典
Env = Dict[Text, Any]  # 字典 key 是 str, value 是任意类型

请求方法

# 枚举类,其中属性是 Text类型
class MethodEnum(Text, Enum):
    GET = "GET"
    POST = "POST"
    PUT = "PUT"
    DELETE = "DELETE"
    HEAD = "HEAD"
    OPTIONS = "OPTIONS"
    PATCH = "PATCH"

其余模型

避免篇幅过长,这里直接复制源代码 附上注释

class TConfig(BaseModel):
    """测试配置模型"""
    name: Name
    verify: Verify = False
    base_url: BaseUrl = ""
    # Text: prepare variables in debugtalk.py, ${gen_variables()}
    # 变量
    variables: Union[VariablesMapping, Text] = {}
    parameters: Union[VariablesMapping, Text] = {}
    # setup_hooks: Hooks = []
    # teardown_hooks: Hooks = []
    export: Export = []
    path: Text = None
    weight: int = 1


class TRequest(BaseModel):
    """测试请求模型"""
    """requests.Request model"""

    method: MethodEnum  # 这里的类型是前面定义的请求方法枚举
    url: Url  
    # 查询参数
    params: Dict[Text, Text] = {}
    headers: Headers = {}
    # alias 是别名, json 数据
    req_json: Union[Dict, List, Text] = Field(None, alias="json")
    # data 数据 - 表单
    data: Union[Text, Dict[Text, Any]] = None
    cookies: Cookies = {}
    timeout: float = 120
    # 允许重定向
    allow_redirects: bool = True
    # 安全验证
    verify: Verify = False
    upload: Dict = {}  # used for upload files


class TStep(BaseModel):
    """测试步骤模型"""
    name: Name
    # 步骤可以是一个请求模型
    request: Union[TRequest, None] = None
    # 用例
    testcase: Union[Text, Callable, None] = None
    # 变量
    variables: VariablesMapping = {}
    setup_hooks: Hooks = []
    teardown_hooks: Hooks = []
    # used to extract request's response field
    # 提取响应字段
    extract: VariablesMapping = {}
    # used to export session variables from referenced testcase
    # 导出字段
    export: Export = []
    # 验证器
    validators: Validators = Field([], alias="validate")
    # 验证脚本
    validate_script: List[Text] = []


class TestCase(BaseModel):
    """测试用例模型 = 测试配置 + 测试步骤"""
    config: TConfig
    teststeps: List[TStep]


class ProjectMeta(BaseModel):
    """项目配置模型"""
    # debugtalk.py 文件内容
    debugtalk_py: Text = ""  # debugtalk.py file content
    debugtalk_path: Text = ""  # debugtalk.py file path
    # .env 文件路径
    dot_env_path: Text = ""  # .env file path
    # 在 debugtalk.py 中定义的函数
    functions: FunctionsMapping = {}  # functions defined in debugtalk.py
    env: Env = {}
    # 项目根目录
    RootDir: Text = os.getcwd()  # project root directory (ensure absolute), the path debugtalk.py located


class TestsMapping(BaseModel):
    """测试集合"""
    project_meta: ProjectMeta
    testcases: List[TestCase]


class TestCaseTime(BaseModel):
    """测试用例时间"""
    start_at: float = 0
    start_at_iso_format: Text = ""
    duration: float = 0


class TestCaseInOut(BaseModel):
    """测试用例输入输出"""
    # 输入参数
    config_vars: VariablesMapping = {}
    # 导出参数
    export_vars: Dict = {}


class RequestStat(BaseModel):
    """请求状态"""
    content_size: float = 0
    response_time_ms: float = 0
    elapsed_ms: float = 0


class AddressData(BaseModel):
    """地址数据"""
    client_ip: Text = "N/A"
    client_port: int = 0
    server_ip: Text = "N/A"
    server_port: int = 0


class RequestData(BaseModel):
    """请求数据模型"""
    method: MethodEnum = MethodEnum.GET
    url: Url
    headers: Headers = {}
    cookies: Cookies = {}
    body: Union[Text, bytes, List, Dict, None] = {}


class ResponseData(BaseModel):
    """响应数据模型"""
    status_code: int
    headers: Dict
    cookies: Cookies
    encoding: Union[Text, None] = None
    content_type: Text
    body: Union[Text, bytes, List, Dict]


class ReqRespData(BaseModel):
    """请求响应数据模型"""
    request: RequestData
    response: ResponseData


class SessionData(BaseModel):
    """会话数据"""
    """request session data, including request, response, validators and stat data"""

    success: bool = False
    # in most cases, req_resps only contains one request & response
    # while when 30X redirect occurs, req_resps will contain multiple request & response
    req_resps: List[ReqRespData] = []
    stat: RequestStat = RequestStat()
    address: AddressData = AddressData()
    validators: Dict = {}


class StepData(BaseModel):
    """步骤数据模型"""
    """teststep data, each step maybe corresponding to one request or one testcase"""

    success: bool = False
    name: Text = ""  # teststep name
    data: Union[SessionData, List['StepData']] = None
    export_vars: VariablesMapping = {}

        
StepData.update_forward_refs()


class TestCaseSummary(BaseModel):
    """测试用例结果"""
    name: Text
    success: bool
    case_id: Text
    time: TestCaseTime
    in_out: TestCaseInOut = {}
    log: Text = ""
    step_datas: List[StepData] = []


class PlatformInfo(BaseModel):
    httprunner_version: Text
    python_version: Text
    platform: Text


class TestCaseRef(BaseModel):
    name: Text
    base_url: Text = ""
    testcase: Text
    variables: VariablesMapping = {}


class TestSuite(BaseModel):
    """测试套件"""
    config: TConfig
    testcases: List[TestCaseRef]


class Stat(BaseModel):
    """结果集状态"""
    total: int = 0
    success: int = 0
    fail: int = 0


class TestSuiteSummary(BaseModel):
    """测试套件结果收集"""
    success: bool = False
    stat: Stat = Stat()
    time: TestCaseTime = TestCaseTime()
    platform: PlatformInfo
    testcases: List[TestCaseSummary]

最后

上述内容个人理解,如有错误欢迎指出交流。

标签:定义,Union,Text,List,HttpRunner3,源码,Dict,BaseModel,class
来源: https://www.cnblogs.com/zy7y/p/15093604.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有