Files
httprunner/httprunner/models.py
duanchao.bill 654edabe78 fix: codeview
2022-05-06 22:37:04 +08:00

306 lines
7.3 KiB
Python

import os
from enum import Enum
from typing import Any, Callable, Dict, List, Text, Union
from pydantic import BaseModel, Field, HttpUrl
Name = Text
Url = Text
BaseUrl = Union[HttpUrl, Text]
VariablesMapping = Dict[Text, Any]
FunctionsMapping = Dict[Text, Callable]
Headers = Dict[Text, Text]
Cookies = Dict[Text, Text]
Verify = bool
Hooks = List[Union[Text, Dict[Text, Text]]]
Export = List[Text]
Validators = List[Dict]
Env = Dict[Text, Any]
class MethodEnum(Text, Enum):
GET = "GET"
POST = "POST"
PUT = "PUT"
DELETE = "DELETE"
HEAD = "HEAD"
OPTIONS = "OPTIONS"
PATCH = "PATCH"
class ProtoType(Enum):
Binary = 1
CyBinary = 2
Compact = 3
Json = 4
class TransType(Enum):
Buffered = 1
CyBuffered = 2
Framed = 3
CyFramed = 4
# configs for thrift rpc
class TConfigThrift(BaseModel):
psm: Text = None
env: Text = None
cluster: Text = None
target: Text = None
include_dirs: List[Text] = None
thrift_client: Any = None
timeout: int = 10
idl_path: Text = None
method: Text = None
ip: Text = "127.0.0.1"
port: int = 9000
service_name: Text = None
proto_type: ProtoType = ProtoType.Binary
trans_type: TransType = TransType.Buffered
# configs for db
class TConfigDB(BaseModel):
psm: Text = None
user: Text = None
password: Text = None
ip: Text = None
port: int = 3306
database: Text = None
class TransportEnum(Text, Enum):
BUFFERED = "buffered"
FRAMED = "framed"
class TThriftRequest(BaseModel):
"""rpc request model"""
method: Text = ""
params: Dict = {}
thrift_client: Any = None
idl_path: Text = "" # idl local path
timeout: int = 10 # sec
transport: TransportEnum = TransportEnum.BUFFERED
include_dirs: List[Union[Text, None]] = [] # param of thriftpy2.load
target: Text = "" # tcp://{ip}:{port} or sd://psm?cluster=xx&env=xx
env: Text = "prod"
cluster: Text = "default"
psm: Text = ""
service_name: Text = None
ip: Text = None
port: int = None
proto_type: ProtoType = None
trans_type: TransType = None
class SqlMethodEnum(Text, Enum):
FETCHONE = "FETCHONE"
FETCHMANY = "FETCHMANY"
FETCHALL = "FETCHALL"
INSERT = "INSERT"
UPDATE = "UPDATE"
DELETE = "DELETE"
class TSqlRequest(BaseModel):
"""sql request model"""
db_config: TConfigDB = TConfigDB()
method: SqlMethodEnum = None
sql: Text = None
size: int = 0 # limit nums of sql result
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
# configs for other protocols
thrift: TConfigThrift = None
db: TConfigDB = TConfigDB()
class TRequest(BaseModel):
"""requests.Request model"""
method: MethodEnum
url: Url
params: Dict[Text, Text] = {}
headers: Headers = {}
req_json: Union[Dict, List, Text] = Field(None, alias="json")
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] = []
retry_times: int = 0
retry_interval: int = 0 # sec
thrift_request: Union[TThriftRequest, None] = None
sql_request: Union[TSqlRequest, None] = None
class TestCase(BaseModel):
config: TConfig
teststeps: List[TStep]
class ProjectMeta(BaseModel):
debugtalk_py: Text = "" # debugtalk.py file content
debugtalk_path: Text = "" # debugtalk.py file path
dot_env_path: Text = "" # .env file path
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, None]
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 StepResult(BaseModel):
"""teststep data, each step maybe corresponding to one request or one testcase"""
name: Text = "" # teststep name
step_type: Text = "" # teststep type, request or testcase
success: bool = False
data: Union[SessionData, List["StepResult"]] = None
elapsed: float = 0.0 # teststep elapsed time
content_size: float = 0 # response content size
export_vars: VariablesMapping = {}
attachment: Text = "" # teststep attachment
StepResult.update_forward_refs()
class IStep(object):
def name(self) -> str:
raise NotImplementedError
def type(self) -> str:
raise NotImplementedError
def struct(self) -> TStep:
raise NotImplementedError
def run(self, runner) -> StepResult:
# runner: HttpRunner
raise NotImplementedError
class TestCaseSummary(BaseModel):
name: Text
success: bool
case_id: Text
time: TestCaseTime
in_out: TestCaseInOut = {}
log: Text = ""
step_results: List[StepResult] = []
class PlatformInfo(BaseModel):
httprunner_version: Text
python_version: Text
platform: Text
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]