Files
InterfaceAutoTest/core/models.py
CNWei 00791809df refactor: 重构执行引擎为上下文驱动架构
- 优化 WorkflowExecutor 与 Exchange支持 ExecutionEnv 资源注入。
 - 实现 Session 级别连接复用与变量池内存镜像化,消除重复 I/O 开销。
 - 引入 ChainMap 实现动态上下文切换,解决参数化变量与全局提取变量的优先级覆盖。
 - 完善变量提取与断言逻辑,确保跨用例变量流转的可靠性。
2026-03-14 11:45:52 +08:00

129 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
# coding=utf-8
"""
@author: chen wei
@Software: PyCharm
@contact: t6i888@163.com
@file: models.py
@date: 2024 2024/9/15 21:14
@desc: 声明yaml用例格式
"""
import logging
from typing import List, Any
from pydantic import BaseModel, Field, ConfigDict
logger = logging.getLogger(__name__)
class HttpAction(BaseModel):
method: str = Field(..., description="HTTP 请求方法: get, post, etc.")
url: str = Field(..., description="接口路径或完整 URL")
headers: dict[str, Any] | None = Field(default=None, description="HTTP 请求头")
params: dict[str, Any] | None = Field(default=None, description="URL 查询参数")
data: dict[str, Any] | None = None
json_body: Any | None = Field(default=None, alias="json")
timeout: int = 10
files: dict[str, Any] | None = None
model_config = ConfigDict(extra="allow", populate_by_name=True)
class ApiActionModel(BaseModel):
module: str = Field(..., alias="class", description="要调用的 API 类名")
method: str = Field(..., description="类中的方法名")
params: dict[str, Any] = Field(default_factory=dict, description="传给方法的参数")
model_config = ConfigDict(populate_by_name=True)
class ValidateItem(BaseModel):
check: str = Field(..., description="要检查的字段或表达式")
assert_method: str = Field(alias="assert", default="equals")
expect: Any = Field(..., description="期望值")
msg: str = Field(default="Assertion", description="断言描述")
model_config = ConfigDict(populate_by_name=True)
class RawSchema(BaseModel):
title: str = Field(..., description="用例标题")
epic: str | None = None
feature: str | None = None
story: str | None = None
# 统一使用 action 字段承载业务逻辑 (Http 或 PO)
action: dict[str, Any] = Field(description="请求内容或PO动作内容")
extract: dict[str, List[Any]] | None = Field(
default=None,
description="变量提取表达式,格式: {变量名: [来源, 表达式, 索引]}"
)
validate_data: List[Any] = Field(
default_factory=list,
alias="validate",
description="断言信息"
)
model_config = ConfigDict(extra="allow",
populate_by_name=True, # 无论是在代码中用 api_class 还是在 YAML 中用 class 赋值Pydantic 都能正确识别。
arbitrary_types_allowed=True # 允许在模型中使用非 Pydantic 标准类型(如自定义类实例)
) # 允许参数化等额外字段
def is_po_mode(self) -> bool:
"""判断是否为 PO 模式"""
return "class" in self.action or "module" in self.action
if __name__ == '__main__':
# 模拟数据 1标准请求模式
raw_case_1 = {
"title": "查询状态信息",
"action": {
"method": "get",
"url": "/api/v1/info",
"headers": {"User-Agent": "pytest-ai"},
"json": {"User-Agent": "pytest-ai"}
},
"validate": [
{"check": "status_code", "assert": "equals", "expect": 200, "msg": "响应码200"},
{"check": "$.msg", "expect": "Success"}
]
}
# 模拟数据 2PO 模式 (反射调用)
raw_case_2 = {
"title": "用户登录测试",
"action": {
"class": "UserAPI",
"method": "login",
"params": {"user": "admin", "pwd": "123"}
},
"extract": {
"token": ["json", "$.data.token", 0]
}
}
print("--- 开始模型校验测试 ---\n")
try:
# 验证模式 1
case1 = RawSchema(**raw_case_1)
print(f"✅ 模式1 (Request) 校验通过: {case1.title}")
print(f" http: {case1.action}")
print(f" 断言规则数: {len(case1.validate_data)}\n")
# 验证模式 2
case2 = RawSchema(**raw_case_2)
print(f"✅ 模式2 (PO Mode) 校验通过: {case2.title}")
print(f" api: {case2.action}")
print(f" 提取规则数: {len(case2.extract)}\n")
# 验证非法数据(如:既没有 request 也没有 api_action 的情况可以在业务层进一步校验)
# 这里演示 Pydantic 自动类型转换
invalid_data = {"title": "错误用例", "action": {"url": "/api"}} # 缺少 method
print("--- 预期失败测试 ---")
RawSchema(**invalid_data)
except Exception as e:
print(f"❌ 预期内的校验失败: \n{e}")