#!/usr/bin/env python # coding=utf-8 """ @desc: 核心测试用例执行引擎 """ import logging import importlib from typing import Any from commons.models.case_model import CaseInfo from core.session import Session from commons.exchange import Exchange from commons.asserts import Asserts logger = logging.getLogger(__name__) class WorkflowExecutor: def __init__(self, session: Session, exchanger: Exchange): self.session = session self.exchanger = exchanger def perform(self, case_data: dict) -> Any: """执行单个用例:支持直接请求和PO模式调用""" # 1. 变量替换(将 ${var} 替换为真实值) rendered_case = self.exchanger.replace(case_data) # 2. 决定执行模式 if "api_action" in rendered_case: # --- PO 模式:反射调用业务层 --- action = rendered_case["api_action"] resp = self._execute_po_method( class_name=action["class"], method_name=action["method"], params=action.get("params", {}) ) else: # --- 数据驱动模式:直接发送请求 --- # 使用 Pydantic 校验 request 结构 case_info = CaseInfo(**rendered_case) request_info = case_info.request.model_dump(by_alias=True, exclude_none=True) resp = self.session.request(**request_info) # 3. 提取变量 (接口关联) if rendered_case.get("extract"): for var_name, extract_info in rendered_case["extract"].items(): self.exchanger.extract(resp, var_name, *extract_info) # 4. 断言校验 if rendered_case.get("validate"): Asserts.validate(resp, rendered_case["validate"]) return resp def _execute_po_method(self, class_name: str, method_name: str, params: dict): """核心反射逻辑:根据字符串动态加载 api/ 目录下的类并执行方法""" try: # 1. 动态导入模块(假设都在 api 目录下) # 例如 class_name 是 UserAPI,则尝试从 api.user 导入 # 这里简单处理,你可以根据你的文件名约定进一步优化逻辑 module_name = f"api.{class_name.lower().replace('api', '')}" module = importlib.import_module(module_name) # 2. 获取类并实例化 cls = getattr(module, class_name) api_instance = cls(self.session) # 传入 session 保持会话统一 # 3. 调用方法并返回结果 method = getattr(api_instance, method_name) logger.info(f"🚀 调用业务层: {class_name}.{method_name} 参数: {params}") return method(**params) except Exception as e: logger.error(f"反射调用失败: {class_name}.{method_name} -> {e}") raise