fix llm
This commit is contained in:
parent
a4e175bc15
commit
b3ac2408be
@ -18,7 +18,7 @@
|
||||
* 对每一个选定的 API 端点:
|
||||
* 通过 `TestCaseRegistry` 获取所有适用于该端点的自定义测试用例类。
|
||||
* 实例化每个测试用例类。
|
||||
* 调用 `_prepare_initial_request_data` 方法准备初始请求数据(路径参数、查询参数、请求头、请求体)。此方法会根据全局配置和测试用例自身的配置决定是否使用 LLM 进行数据生成,并利用 `LLMService` 和动态 Pydantic 模型创建(`_create_pydantic_model_from_schema`)来实现。如果LLM未启用或不适用,则使用传统的基于 Schema 的数据生成逻辑(`_generate_params_from_list`, `_generate_data_from_schema`)。此阶段还实现了端点级别的LLM参数缓存。
|
||||
* 调用 `_prepare_initial_request_data` 方法准备初始请求数据(路径参数、查询参数、请求头、请求体)。此方法会根据全局配置和测试用例自身的配置决定是否使用 LLM 进行数据生成,并利用 `LLMService` 和动态 Pydantic 模型创建(`_create_pydantic_model_from_schema`)来实现。如果LLM未启用或不适用,则使用传统的基于 Schema 的数据生成逻辑(`_generate_params_from_list`, `_generate_parameters_from_schema`)。此阶段还实现了端点级别的LLM参数缓存。
|
||||
* 依次调用测试用例实例中定义的 `generate_*` 方法,允许测试用例修改生成的请求数据。
|
||||
* 调用测试用例实例中定义的 `validate_request_*` 方法,对即将发送的请求进行预校验。
|
||||
* 使用 `APICaller` 发送最终构建的 API 请求。
|
||||
@ -132,7 +132,7 @@
|
||||
* `validate_response(self, response_context: APIResponseContext, request_context: APIRequestContext) -> List[ValidationResult]`
|
||||
* 检查状态码、响应头、响应体内容是否符合预期。
|
||||
* 进行业务逻辑相关的断言。
|
||||
* **性能检查方法 (可选)**:
|
||||
* **性能检查方法**:
|
||||
|
||||
* `check_performance(self, response_context: APIResponseContext, request_context: APIRequestContext) -> List[ValidationResult]`
|
||||
* 通常用于检查响应时间 `response_context.elapsed_time`。
|
||||
|
||||
1998
api_call_details.md
1998
api_call_details.md
File diff suppressed because it is too large
Load Diff
3379
api_calls.md
3379
api_calls.md
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -14,7 +14,7 @@ class StatusCode200Check(BaseAPITestCase):
|
||||
# applicable_paths_regex = None
|
||||
execution_order = 1 # 执行顺序
|
||||
is_critical_setup_test = True
|
||||
# use_llm_for_body: bool = True
|
||||
use_llm_for_body: bool = True
|
||||
# use_llm_for_path_params: bool = True
|
||||
# use_llm_for_query_params: bool = True
|
||||
# use_llm_for_headers: bool = True
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -5,7 +5,6 @@ import json
|
||||
import logging
|
||||
import re
|
||||
from typing import Optional, Dict, Any, List
|
||||
|
||||
import requests
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic.json_schema import models_json_schema
|
||||
@ -59,7 +58,7 @@ class LLMService:
|
||||
self,
|
||||
messages: List[Dict[str, str]],
|
||||
max_tokens: int = 1024,
|
||||
temperature: float = 0.7,
|
||||
temperature: float = 0.1,
|
||||
# TODO: Consider adding a parameter like response_format_type: Optional[str] = None
|
||||
# if the LLM API supports forcing JSON output (e.g., { "type": "json_object" })
|
||||
) -> Optional[str]:
|
||||
@ -114,7 +113,7 @@ class LLMService:
|
||||
pydantic_model_class: type[BaseModel],
|
||||
prompt_instruction: Optional[str] = None,
|
||||
max_tokens: int = 1024,
|
||||
temperature: float = 0.7
|
||||
temperature: float = 0.1
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
根据给定的Pydantic模型类生成JSON Schema,并调用LLM生成符合该Schema的参数字典。
|
||||
@ -178,6 +177,65 @@ class LLMService:
|
||||
|
||||
return None
|
||||
|
||||
def generate_data_from_schema(
|
||||
self,
|
||||
schema_dict: dict,
|
||||
prompt_instruction: Optional[str] = None,
|
||||
max_tokens: int = 1024,
|
||||
temperature: float = 0.1
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
根据给定的JSON Schema字典,调用LLM生成符合该Schema的数据对象。
|
||||
"""
|
||||
try:
|
||||
schema_str = json.dumps(schema_dict, indent=2, ensure_ascii=False)
|
||||
logger.debug(f"LLMService.generate_data_from_schema: 使用的JSON Schema:\n{schema_str}")
|
||||
|
||||
system_prompt = (
|
||||
"你是一个API测试数据生成助手。你的任务是根据用户提供的JSON Schema和额外指令,"
|
||||
"生成一个符合该Schema的JSON对象。请确保你的输出严格是一个JSON对象,"
|
||||
"不包含任何额外的解释、注释或Markdown标记。"
|
||||
)
|
||||
user_prompt_content = f"请为以下JSON Schema生成一个有效的JSON对象实例:\n\n```json\n{schema_str}\n```\n"
|
||||
if prompt_instruction:
|
||||
user_prompt_content += f"\n请遵循以下额外指令:\n{prompt_instruction}"
|
||||
messages = [
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": user_prompt_content}
|
||||
]
|
||||
|
||||
assistant_response_content = self._execute_chat_completion_request(
|
||||
messages=messages,
|
||||
max_tokens=max_tokens,
|
||||
temperature=temperature
|
||||
)
|
||||
|
||||
if assistant_response_content:
|
||||
# 尝试从返回内容中提取JSON部分
|
||||
json_match = re.search(r'```json\n(.*?)\n```', assistant_response_content, re.DOTALL)
|
||||
if json_match:
|
||||
json_str = json_match.group(1)
|
||||
else:
|
||||
first_brace = assistant_response_content.find('{')
|
||||
last_brace = assistant_response_content.rfind('}')
|
||||
if first_brace != -1 and last_brace != -1 and last_brace > first_brace:
|
||||
json_str = assistant_response_content[first_brace : last_brace+1]
|
||||
else:
|
||||
json_str = assistant_response_content
|
||||
|
||||
try:
|
||||
generated_data = json.loads(json_str)
|
||||
logger.info("成功从LLM生成并解析了数据。")
|
||||
return generated_data
|
||||
except json.JSONDecodeError as e_json:
|
||||
logger.error(f"无法将LLM响应解析为JSON: {e_json}\n原始响应片段: '{json_str[:500]}'")
|
||||
else:
|
||||
logger.warning("从LLM获取的响应内容为空或请求失败。")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"执行LLM数据生成时发生未知错误: {e}", exc_info=True)
|
||||
return None
|
||||
|
||||
# --- 示例用法 (用于模块内测试) ---
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.DEBUG,
|
||||
|
||||
@ -1029,85 +1029,117 @@ class APITestOrchestrator:
|
||||
|
||||
# 1. 处理路径参数
|
||||
path_param_specs = [p for p in parameters if p.get('in') == 'path']
|
||||
for param_spec in path_param_specs:
|
||||
name = param_spec.get('name')
|
||||
if not name: continue
|
||||
|
||||
if path_param_specs:
|
||||
should_use_llm = self._should_use_llm_for_param_type("path_params", test_case_instance)
|
||||
if should_use_llm and self.llm_service:
|
||||
self.logger.info(f"Attempting LLM generation for path parameter '{name}' in '{operation_id}'")
|
||||
# generated_value = self.llm_service.generate_data_for_parameter(param_spec, endpoint_spec, "path")
|
||||
# initial_path_params[name] = generated_value if generated_value is not None else f"llm_placeholder_for_{name}"
|
||||
initial_path_params[name] = f"llm_path_{name}" # Placeholder
|
||||
else:
|
||||
if 'example' in param_spec:
|
||||
initial_path_params[name] = param_spec['example']
|
||||
elif param_spec.get('schema') and 'example' in param_spec['schema']:
|
||||
initial_path_params[name] = param_spec['schema']['example'] # OpenAPI 3.0 `parameter.schema.example`
|
||||
elif 'default' in param_spec.get('schema', {}):
|
||||
initial_path_params[name] = param_spec['schema']['default']
|
||||
elif 'default' in param_spec: # OpenAPI 2.0 `parameter.default`
|
||||
initial_path_params[name] = param_spec['default']
|
||||
self.logger.info(f"Attempting LLM generation for path parameters in '{operation_id}'")
|
||||
path_schema, path_model_name = self._build_object_schema_for_params(path_param_specs, f"{operation_id}_PathParams")
|
||||
if path_schema:
|
||||
llm_path_params = self.llm_service.generate_data_from_schema(
|
||||
path_schema,
|
||||
prompt_instruction=None,
|
||||
max_tokens=256,
|
||||
temperature=0.1
|
||||
)
|
||||
if llm_path_params:
|
||||
initial_path_params = llm_path_params
|
||||
else:
|
||||
self.logger.warning(f"LLM failed to generate path params for '{operation_id}', fallback to default.")
|
||||
else:
|
||||
schema = param_spec.get('schema', {})
|
||||
param_type = schema.get('type', 'string')
|
||||
if param_type == 'integer': initial_path_params[name] = 123
|
||||
elif param_type == 'number': initial_path_params[name] = 1.23
|
||||
elif param_type == 'boolean': initial_path_params[name] = True
|
||||
elif param_type == 'string' and schema.get('format') == 'uuid': initial_path_params[name] = str(UUID(int=0)) # Example UUID
|
||||
elif param_type == 'string' and schema.get('format') == 'date': initial_path_params[name] = dt.date.today().isoformat()
|
||||
elif param_type == 'string' and schema.get('format') == 'date-time': initial_path_params[name] = dt.datetime.now().isoformat()
|
||||
else: initial_path_params[name] = f"param_{name}"
|
||||
self.logger.debug(f"Initial path param for '{operation_id}': {name} = {initial_path_params.get(name)}")
|
||||
|
||||
self.logger.warning(f"Failed to build schema for path params in '{operation_id}', fallback to default.")
|
||||
if not initial_path_params: # fallback
|
||||
for param_spec in path_param_specs:
|
||||
name = param_spec.get('name')
|
||||
if not name: continue
|
||||
if 'example' in param_spec:
|
||||
initial_path_params[name] = param_spec['example']
|
||||
elif param_spec.get('schema') and 'example' in param_spec['schema']:
|
||||
initial_path_params[name] = param_spec['schema']['example'] # OpenAPI 3.0 `parameter.schema.example`
|
||||
elif 'default' in param_spec.get('schema', {}):
|
||||
initial_path_params[name] = param_spec['schema']['default']
|
||||
elif 'default' in param_spec: # OpenAPI 2.0 `parameter.default`
|
||||
initial_path_params[name] = param_spec['default']
|
||||
else:
|
||||
schema = param_spec.get('schema', {})
|
||||
param_type = schema.get('type', 'string')
|
||||
if param_type == 'integer': initial_path_params[name] = 123
|
||||
elif param_type == 'number': initial_path_params[name] = 1.23
|
||||
elif param_type == 'boolean': initial_path_params[name] = True
|
||||
elif param_type == 'string' and schema.get('format') == 'uuid': initial_path_params[name] = str(UUID(int=0)) # Example UUID
|
||||
elif param_type == 'string' and schema.get('format') == 'date': initial_path_params[name] = dt.date.today().isoformat()
|
||||
elif param_type == 'string' and schema.get('format') == 'date-time': initial_path_params[name] = dt.datetime.now().isoformat()
|
||||
else: initial_path_params[name] = f"param_{name}"
|
||||
self.logger.debug(f"Initial path param for '{operation_id}': {initial_path_params}")
|
||||
|
||||
# 2. 处理查询参数
|
||||
query_param_specs = [p for p in parameters if p.get('in') == 'query']
|
||||
for param_spec in query_param_specs:
|
||||
name = param_spec.get('name')
|
||||
if not name: continue
|
||||
if query_param_specs:
|
||||
should_use_llm = self._should_use_llm_for_param_type("query_params", test_case_instance)
|
||||
if should_use_llm and self.llm_service:
|
||||
self.logger.info(f"Attempting LLM generation for query parameter '{name}' in '{operation_id}'")
|
||||
initial_query_params[name] = f"llm_query_{name}" # Placeholder
|
||||
else:
|
||||
if 'example' in param_spec:
|
||||
initial_query_params[name] = param_spec['example']
|
||||
elif param_spec.get('schema') and 'example' in param_spec['schema']:
|
||||
initial_query_params[name] = param_spec['schema']['example']
|
||||
elif 'default' in param_spec.get('schema', {}):
|
||||
initial_query_params[name] = param_spec['schema']['default']
|
||||
elif 'default' in param_spec:
|
||||
initial_query_params[name] = param_spec['default']
|
||||
else:
|
||||
initial_query_params[name] = f"query_val_{name}" # Simplified default
|
||||
self.logger.debug(f"Initial query param for '{operation_id}': {name} = {initial_query_params.get(name)}")
|
||||
|
||||
self.logger.info(f"Attempting LLM generation for query parameters in '{operation_id}'")
|
||||
query_schema, query_model_name = self._build_object_schema_for_params(query_param_specs, f"{operation_id}_QueryParams")
|
||||
if query_schema:
|
||||
llm_query_params = self.llm_service.generate_data_from_schema(
|
||||
query_schema,
|
||||
prompt_instruction=None,
|
||||
max_tokens=512,
|
||||
temperature=0.1
|
||||
)
|
||||
if llm_query_params:
|
||||
initial_query_params = llm_query_params
|
||||
else:
|
||||
self.logger.warning(f"LLM failed to generate query params for '{operation_id}', fallback to default.")
|
||||
if not initial_query_params: # fallback
|
||||
for param_spec in query_param_specs:
|
||||
name = param_spec.get('name')
|
||||
if not name: continue
|
||||
if 'example' in param_spec:
|
||||
initial_query_params[name] = param_spec['example']
|
||||
elif param_spec.get('schema') and 'example' in param_spec['schema']:
|
||||
initial_query_params[name] = param_spec['schema']['example']
|
||||
elif 'default' in param_spec.get('schema', {}):
|
||||
initial_query_params[name] = param_spec['schema']['default']
|
||||
elif 'default' in param_spec:
|
||||
initial_query_params[name] = param_spec['default']
|
||||
else:
|
||||
initial_query_params[name] = f"query_val_{name}"
|
||||
self.logger.debug(f"Initial query param for '{operation_id}': {initial_query_params}")
|
||||
|
||||
# 3. 处理请求头参数 (包括规范定义的和标准的 Content-Type/Accept)
|
||||
header_param_specs = [p for p in parameters if p.get('in') == 'header']
|
||||
for param_spec in header_param_specs:
|
||||
name = param_spec.get('name')
|
||||
if not name: continue
|
||||
# 标准头 Content-Type 和 Accept 会在后面专门处理
|
||||
if name.lower() in ['content-type', 'accept', 'authorization']:
|
||||
self.logger.debug(f"Skipping standard header '{name}' in parameter processing for '{operation_id}'. It will be handled separately.")
|
||||
continue
|
||||
|
||||
custom_header_param_specs = [p for p in header_param_specs if p.get('name', '').lower() not in ['content-type', 'accept', 'authorization']]
|
||||
if custom_header_param_specs:
|
||||
should_use_llm = self._should_use_llm_for_param_type("headers", test_case_instance)
|
||||
if should_use_llm and self.llm_service:
|
||||
self.logger.info(f"Attempting LLM generation for header '{name}' in '{operation_id}'")
|
||||
initial_headers[name] = f"llm_header_{name}" # Placeholder
|
||||
else:
|
||||
if 'example' in param_spec:
|
||||
initial_headers[name] = str(param_spec['example'])
|
||||
elif param_spec.get('schema') and 'example' in param_spec['schema']:
|
||||
initial_headers[name] = str(param_spec['schema']['example'])
|
||||
elif 'default' in param_spec.get('schema', {}):
|
||||
initial_headers[name] = str(param_spec['schema']['default'])
|
||||
elif 'default' in param_spec:
|
||||
initial_headers[name] = str(param_spec['default'])
|
||||
else:
|
||||
initial_headers[name] = f"header_val_{name}"
|
||||
self.logger.debug(f"Initial custom header param for '{operation_id}': {name} = {initial_headers.get(name)}")
|
||||
self.logger.info(f"Attempting LLM generation for header parameters in '{operation_id}'")
|
||||
header_schema, header_model_name = self._build_object_schema_for_params(custom_header_param_specs, f"{operation_id}_HeaderParams")
|
||||
if header_schema:
|
||||
llm_header_params = self.llm_service.generate_data_from_schema(
|
||||
header_schema,
|
||||
prompt_instruction=None,
|
||||
max_tokens=256,
|
||||
temperature=0.1
|
||||
)
|
||||
if llm_header_params:
|
||||
for k, v in llm_header_params.items():
|
||||
initial_headers[k] = str(v)
|
||||
else:
|
||||
self.logger.warning(f"LLM failed to generate header params for '{operation_id}', fallback to default.")
|
||||
if not any(k for k in initial_headers if k.lower() not in ['content-type', 'accept', 'authorization']): # fallback
|
||||
for param_spec in custom_header_param_specs:
|
||||
name = param_spec.get('name')
|
||||
if not name: continue
|
||||
if 'example' in param_spec:
|
||||
initial_headers[name] = str(param_spec['example'])
|
||||
elif param_spec.get('schema') and 'example' in param_spec['schema']:
|
||||
initial_headers[name] = str(param_spec['schema']['example'])
|
||||
elif 'default' in param_spec.get('schema', {}):
|
||||
initial_headers[name] = str(param_spec['schema']['default'])
|
||||
elif 'default' in param_spec:
|
||||
initial_headers[name] = str(param_spec['default'])
|
||||
else:
|
||||
initial_headers[name] = f"header_val_{name}"
|
||||
self.logger.debug(f"Initial custom header param for '{operation_id}': {initial_headers}")
|
||||
|
||||
# 3.1 设置 Content-Type
|
||||
# 优先从 requestBody.content 获取 (OpenAPI 3.x)
|
||||
@ -1163,7 +1195,12 @@ class APITestOrchestrator:
|
||||
should_use_llm_for_body = self._should_use_llm_for_param_type("body", test_case_instance)
|
||||
if should_use_llm_for_body and self.llm_service:
|
||||
self.logger.info(f"Attempting LLM generation for request body of '{operation_id}' with schema...")
|
||||
initial_body = self.llm_service.generate_data_from_schema(request_body_schema, endpoint_spec, "requestBody")
|
||||
initial_body = self.llm_service.generate_data_from_schema(
|
||||
request_body_schema,
|
||||
prompt_instruction=None, # 如有自定义指令可替换
|
||||
max_tokens=1024,
|
||||
temperature=0.1
|
||||
)
|
||||
if initial_body is None:
|
||||
self.logger.warning(f"LLM failed to generate request body for '{operation_id}'. Falling back to default schema generator.")
|
||||
initial_body = self._generate_data_from_schema(request_body_schema, context_name=f"{operation_id}_body", operation_id=operation_id)
|
||||
|
||||
47
ppt.md
Normal file
47
ppt.md
Normal file
@ -0,0 +1,47 @@
|
||||
# BaseAPITestCase 核心方法能力一览
|
||||
|
||||
## 1. 生命周期钩子方法(可重写)
|
||||
|
||||
| 方法名 | 能力描述 |
|
||||
| ---------------------------- | ---------------------------------------------------------------- |
|
||||
| `__init__` | 初始化测试用例,加载接口 schema、参数、上下文等 |
|
||||
| `generate_path_params` | 生成/修改路径参数(如 `/user/{id}` 中的 `id`),支持动态构造 |
|
||||
| `generate_query_params` | 生成/修改 query 参数,支持边界值、缺失、类型异常等场景 |
|
||||
| `generate_headers` | 生成/修改请求头,支持鉴权、格式异常等测试 |
|
||||
| `generate_request_body` | 生成/修改请求体,支持字段缺失、类型不符等复杂场景 |
|
||||
| `modify_request_url` | 动态修改请求 URL,适用于特殊路径拼接等需求 |
|
||||
| `validate_request_url` | 请求发送前校验 URL 合规性 |
|
||||
| `validate_request_headers` | 请求发送前校验头部数据 |
|
||||
| `validate_request_body` | 请求发送前校验请求体 |
|
||||
| `validate_response` | 响应校验,断言状态码、响应体、业务逻辑等 |
|
||||
| `check_performance` | 性能校验,检查响应耗时等 |
|
||||
|
||||
## 2. 辅助工具方法(极大简化用例开发)
|
||||
|
||||
| 方法名 | 能力描述 |
|
||||
| ------------------------------------- | ------------------------------------------------------------- |
|
||||
| `_get_resolved_request_body_schema` | 获取并解析当前接口的请求体 schema,自动处理 $ref |
|
||||
| `_find_removable_field_path` | 查找可被移除的必填字段路径,便于生成“缺失字段”场景 |
|
||||
| `_remove_value_at_path` | 按路径从数据中移除指定字段,支持嵌套结构 |
|
||||
| `_find_simple_type_field_in_schema` | 查找 schema 中第一个简单类型字段,便于类型异常测试 |
|
||||
| `_find_first_simple_type_parameter` | 查找第一个简单类型的参数(如 query/header),便于参数异常测试 |
|
||||
| `_find_required_parameter_name` | 查找第一个必填参数名 |
|
||||
| `expect_error_response` | 标准化校验错误响应(状态码、错误码等),减少样板代码 |
|
||||
| `validate_data_against_schema` | 用 schema 校验任意数据结构,便于响应体合规性断言 |
|
||||
| `passed` / `failed` | 快速生成验证结果对象,便于断言输出 |
|
||||
|
||||
## 3. 日志与上下文
|
||||
|
||||
| 方法名/属性 | 能力描述 |
|
||||
| ------------------------ | -------------------------------- |
|
||||
| `self.logger` | 统一日志输出,便于调试与结果追踪 |
|
||||
| `self.endpoint_spec` | 当前接口的详细规范,已处理 $ref |
|
||||
| `self.global_api_spec` | 全局 API 规范,便于跨接口引用 |
|
||||
|
||||
---
|
||||
|
||||
> **说明**:
|
||||
>
|
||||
> - 生命周期钩子方法由框架自动调用,用户可按需重写,实现灵活的请求构造与验证。
|
||||
> - 辅助工具方法极大简化了 schema 处理、字段查找、数据操作等底层细节,让用例开发者专注于业务逻辑。
|
||||
> - 通过这些方法,测试用例可轻松实现“字段缺失、类型异常、参数边界、响应断言、性能校验”等多种自动化测试能力。
|
||||
@ -96,7 +96,7 @@
|
||||
"test_case_name": "Error Code 4001 - Request Body Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "失败",
|
||||
"message": "当请求体字段 'isSearchCount' 类型不匹配时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4001'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '44'.",
|
||||
"message": "当请求体字段 'isSearchCount' 类型不匹配时,期望API返回状态码在 [400, 422] 中,或返回业务码为 '4001'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '44'.",
|
||||
"duration_seconds": 0.02025704109109938,
|
||||
"timestamp": "2025-05-29T16:45:26.000770",
|
||||
"validation_points": [
|
||||
|
||||
897
test_reportllm.json
Normal file
897
test_reportllm.json
Normal file
@ -0,0 +1,897 @@
|
||||
{
|
||||
"summary_metadata": {
|
||||
"start_time": "2025-06-01T00:34:02.816967",
|
||||
"end_time": "2025-06-01T00:34:38.063887",
|
||||
"duration_seconds": "35.25"
|
||||
},
|
||||
"endpoint_stats": {
|
||||
"total_defined": 6,
|
||||
"total_tested": 6,
|
||||
"passed": 0,
|
||||
"failed": 6,
|
||||
"partial_success": 0,
|
||||
"error": 0,
|
||||
"skipped": 0,
|
||||
"success_rate_percentage": "0.00"
|
||||
},
|
||||
"test_case_stats": {
|
||||
"total_applicable": 42,
|
||||
"total_executed": 42,
|
||||
"passed": 24,
|
||||
"failed": 18,
|
||||
"error_in_execution": 0,
|
||||
"skipped_during_endpoint_execution": 0,
|
||||
"success_rate_percentage": "57.14"
|
||||
},
|
||||
"detailed_results": [
|
||||
{
|
||||
"endpoint_id": "POST /api/dms/{dms_instance_code}/v1/message/push/{schema}/{version}",
|
||||
"endpoint_name": "数据推送接口",
|
||||
"overall_status": "失败",
|
||||
"duration_seconds": 7.210219,
|
||||
"start_time": "2025-06-01T00:34:02.817544",
|
||||
"end_time": "2025-06-01T00:34:10.027763",
|
||||
"executed_test_cases": [
|
||||
{
|
||||
"test_case_id": "TC-STATUS-001",
|
||||
"test_case_name": "基本状态码 200 检查",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "响应状态码为 200,符合预期 200。",
|
||||
"duration_seconds": 7.01280862512067,
|
||||
"timestamp": "2025-06-01T00:34:09.830624",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "响应状态码为 200,符合预期 200。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-CORE-FUNC-001",
|
||||
"test_case_name": "Response Body JSON Schema Validation",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "Schema验证步骤完成(未发现问题,或schema不适用/未为此响应定义)。",
|
||||
"duration_seconds": 0.04320399998687208,
|
||||
"timestamp": "2025-06-01T00:34:09.874023",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "Schema验证步骤完成(未发现问题,或schema不适用/未为此响应定义)。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-SECURITY-001",
|
||||
"test_case_name": "HTTPS Protocol Mandatory Verification",
|
||||
"test_case_severity": "严重",
|
||||
"status": "失败",
|
||||
"message": "API通过HTTP (http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/message/push/example_schema/example_version) 响应了成功的状态码 200,这违反了HTTPS强制策略。",
|
||||
"duration_seconds": 0.03913083393126726,
|
||||
"timestamp": "2025-06-01T00:34:09.913300",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-QUERY",
|
||||
"test_case_name": "Error Code 4001 - Query Parameter Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "通过",
|
||||
"message": "跳过测试:在查询参数中未找到合适的字段来测试类型不匹配。",
|
||||
"duration_seconds": 0.026711334008723497,
|
||||
"timestamp": "2025-06-01T00:34:09.940128",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "跳过测试:在查询参数中未找到合适的字段来测试类型不匹配。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-BODY",
|
||||
"test_case_name": "Error Code 4001 - Request Body Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "失败",
|
||||
"message": "当请求体字段 'isSearchCount' 类型不匹配时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4001'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '84'.",
|
||||
"duration_seconds": 0.027765541803091764,
|
||||
"timestamp": "2025-06-01T00:34:09.967981",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 84,
|
||||
"message": "ea",
|
||||
"data": {
|
||||
"total": 90,
|
||||
"list": [
|
||||
{
|
||||
"dsid": "39",
|
||||
"dataRegion": "Duis nostrud",
|
||||
"gasReleaseMon": null,
|
||||
"gasReleaseYear": null,
|
||||
"releaseGasCum": null
|
||||
},
|
||||
{
|
||||
"dsid": "23",
|
||||
"dataRegion": "culpa ea enim et non",
|
||||
"gasReleaseMon": null,
|
||||
"gasReleaseYear": null,
|
||||
"releaseGasCum": null
|
||||
},
|
||||
{
|
||||
"dsid": "50",
|
||||
"dataRegion": "nisi eu nostrud culpa",
|
||||
"gasReleaseMon": null,
|
||||
"gasReleaseYear": null,
|
||||
"releaseGasCum": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4001",
|
||||
"mismatched_field": "body.isSearchCount"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-BODY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Request Body Field Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "通过",
|
||||
"message": "跳过测试:在API规范中未找到合适的必填请求体字段用于移除测试。",
|
||||
"duration_seconds": 0.026672749780118465,
|
||||
"timestamp": "2025-06-01T00:34:09.994986",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "跳过测试:在API规范中未找到合适的必填请求体字段用于移除测试。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-QUERY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Query Parameter Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "通过",
|
||||
"message": "跳过测试:在API规范中未找到合适的必填查询参数用于移除测试。",
|
||||
"duration_seconds": 0.03259733412414789,
|
||||
"timestamp": "2025-06-01T00:34:10.027695",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "跳过测试:在API规范中未找到合适的必填查询参数用于移除测试。"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"endpoint_id": "POST /api/dms/{dms_instance_code}/v1/cd_geo_unit/{version}",
|
||||
"endpoint_name": "地质单元列表查询",
|
||||
"overall_status": "失败",
|
||||
"duration_seconds": 11.292211,
|
||||
"start_time": "2025-06-01T00:34:10.027830",
|
||||
"end_time": "2025-06-01T00:34:21.320041",
|
||||
"executed_test_cases": [
|
||||
{
|
||||
"test_case_id": "TC-STATUS-001",
|
||||
"test_case_name": "基本状态码 200 检查",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "响应状态码为 200,符合预期 200。",
|
||||
"duration_seconds": 11.112421334022656,
|
||||
"timestamp": "2025-06-01T00:34:21.140621",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "响应状态码为 200,符合预期 200。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-CORE-FUNC-001",
|
||||
"test_case_name": "Response Body JSON Schema Validation",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "Schema验证步骤完成(未发现问题,或schema不适用/未为此响应定义)。",
|
||||
"duration_seconds": 0.029472541995346546,
|
||||
"timestamp": "2025-06-01T00:34:21.170422",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "Schema验证步骤完成(未发现问题,或schema不适用/未为此响应定义)。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-SECURITY-001",
|
||||
"test_case_name": "HTTPS Protocol Mandatory Verification",
|
||||
"test_case_severity": "严重",
|
||||
"status": "失败",
|
||||
"message": "API通过HTTP (http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/cd_geo_unit/1.0.0) 响应了成功的状态码 200,这违反了HTTPS强制策略。",
|
||||
"duration_seconds": 0.028989958111196756,
|
||||
"timestamp": "2025-06-01T00:34:21.199627",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-QUERY",
|
||||
"test_case_name": "Error Code 4001 - Query Parameter Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "失败",
|
||||
"message": "当查询参数 'pageNo' (路径: 'pageNo') 类型不匹配时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4001'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '61'.",
|
||||
"duration_seconds": 0.03363720793277025,
|
||||
"timestamp": "2025-06-01T00:34:21.233641",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 61,
|
||||
"message": "dolore ad magna labore",
|
||||
"data": {
|
||||
"total": 17,
|
||||
"list": [
|
||||
{
|
||||
"dsid": "76",
|
||||
"dataRegion": "commodo dolor pariatur laborum reprehenderit",
|
||||
"gasReleaseMon": null,
|
||||
"gasReleaseYear": null,
|
||||
"releaseGasCum": null
|
||||
},
|
||||
{
|
||||
"dsid": "3",
|
||||
"dataRegion": "ut commodo in ea enim",
|
||||
"gasReleaseMon": null,
|
||||
"gasReleaseYear": null,
|
||||
"releaseGasCum": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4001",
|
||||
"mismatched_param": "pageNo"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-BODY",
|
||||
"test_case_name": "Error Code 4001 - Request Body Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "失败",
|
||||
"message": "当请求体字段 'isSearchCount' 类型不匹配时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4001'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '16'.",
|
||||
"duration_seconds": 0.029159249970689416,
|
||||
"timestamp": "2025-06-01T00:34:21.263112",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 16,
|
||||
"message": "nostrud proident enim laborum culpa",
|
||||
"data": {
|
||||
"total": 63,
|
||||
"list": [
|
||||
{
|
||||
"dsid": "66",
|
||||
"dataRegion": "sit ad",
|
||||
"gasReleaseMon": null,
|
||||
"gasReleaseYear": null,
|
||||
"releaseGasCum": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4001",
|
||||
"mismatched_field": "body.isSearchCount"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-BODY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Request Body Field Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "通过",
|
||||
"message": "跳过测试:在API规范中未找到合适的必填请求体字段用于移除测试。",
|
||||
"duration_seconds": 0.028349458938464522,
|
||||
"timestamp": "2025-06-01T00:34:21.291758",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "跳过测试:在API规范中未找到合适的必填请求体字段用于移除测试。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-QUERY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Query Parameter Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "通过",
|
||||
"message": "跳过测试:在API规范中未找到合适的必填查询参数用于移除测试。",
|
||||
"duration_seconds": 0.02780358400195837,
|
||||
"timestamp": "2025-06-01T00:34:21.319898",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "跳过测试:在API规范中未找到合适的必填查询参数用于移除测试。"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"endpoint_id": "PUT /api/dms/{dms_instance_code}/v1/cd_geo_unit",
|
||||
"endpoint_name": "地质单元数据修改",
|
||||
"overall_status": "失败",
|
||||
"duration_seconds": 1.695961,
|
||||
"start_time": "2025-06-01T00:34:21.320157",
|
||||
"end_time": "2025-06-01T00:34:23.016118",
|
||||
"executed_test_cases": [
|
||||
{
|
||||
"test_case_id": "TC-STATUS-001",
|
||||
"test_case_name": "基本状态码 200 检查",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "响应状态码为 200,符合预期 200。",
|
||||
"duration_seconds": 1.529003000119701,
|
||||
"timestamp": "2025-06-01T00:34:22.849539",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "响应状态码为 200,符合预期 200。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-CORE-FUNC-001",
|
||||
"test_case_name": "Response Body JSON Schema Validation",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "针对 PUT http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/cd_geo_unit (状态码 200) 的响应体 conforms to the JSON schema.",
|
||||
"duration_seconds": 0.030560707906261086,
|
||||
"timestamp": "2025-06-01T00:34:22.880198",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "针对 PUT http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/cd_geo_unit (状态码 200) 的响应体 conforms to the JSON schema."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-SECURITY-001",
|
||||
"test_case_name": "HTTPS Protocol Mandatory Verification",
|
||||
"test_case_severity": "严重",
|
||||
"status": "失败",
|
||||
"message": "API通过HTTP (http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/cd_geo_unit) 响应了成功的状态码 200,这违反了HTTPS强制策略。",
|
||||
"duration_seconds": 0.025434250012040138,
|
||||
"timestamp": "2025-06-01T00:34:22.905808",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-QUERY",
|
||||
"test_case_name": "Error Code 4001 - Query Parameter Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "失败",
|
||||
"message": "当查询参数 'id' (路径: 'id') 类型不匹配时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4001'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '50'.",
|
||||
"duration_seconds": 0.02286758297123015,
|
||||
"timestamp": "2025-06-01T00:34:22.928771",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 50,
|
||||
"message": "nulla dolore cillum",
|
||||
"data": false
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4001",
|
||||
"mismatched_param": "id"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-BODY",
|
||||
"test_case_name": "Error Code 4001 - Request Body Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "失败",
|
||||
"message": "当请求体字段 'id' 类型不匹配时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4001'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '17'.",
|
||||
"duration_seconds": 0.031667542178183794,
|
||||
"timestamp": "2025-06-01T00:34:22.960534",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 17,
|
||||
"message": "in",
|
||||
"data": false
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4001",
|
||||
"mismatched_field": "body.id"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-BODY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Request Body Field Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "通过",
|
||||
"message": "当移除必填请求体字段 'id' 时,API响应了状态码 200 (非主要预期HTTP状态 [400, 422],但为4xx客户端错误), 且响应体中包含预期的业务错误码 '4003' (字段: 'code').",
|
||||
"duration_seconds": 0.024940666975453496,
|
||||
"timestamp": "2025-06-01T00:34:22.985617",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "当移除必填请求体字段 'id' 时,API响应了状态码 200 (非主要预期HTTP状态 [400, 422],但为4xx客户端错误), 且响应体中包含预期的业务错误码 '4003' (字段: 'code')."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-QUERY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Query Parameter Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "失败",
|
||||
"message": "当移除必填查询参数 'id' 时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4003'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '47'.",
|
||||
"duration_seconds": 0.030161542119458318,
|
||||
"timestamp": "2025-06-01T00:34:23.015963",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 47,
|
||||
"message": "irure laborum",
|
||||
"data": false
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4003",
|
||||
"removed_param": "query.id"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"endpoint_id": "DELETE /api/dms/{dms_instance_code}/v1/cd_geo_unit",
|
||||
"endpoint_name": "地质单元数据删除",
|
||||
"overall_status": "失败",
|
||||
"duration_seconds": 1.609212,
|
||||
"start_time": "2025-06-01T00:34:23.016230",
|
||||
"end_time": "2025-06-01T00:34:24.625442",
|
||||
"executed_test_cases": [
|
||||
{
|
||||
"test_case_id": "TC-STATUS-001",
|
||||
"test_case_name": "基本状态码 200 检查",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "响应状态码为 200,符合预期 200。",
|
||||
"duration_seconds": 1.438529249979183,
|
||||
"timestamp": "2025-06-01T00:34:24.455129",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "响应状态码为 200,符合预期 200。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-CORE-FUNC-001",
|
||||
"test_case_name": "Response Body JSON Schema Validation",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "针对 DELETE http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/cd_geo_unit (状态码 200) 的响应体 conforms to the JSON schema.",
|
||||
"duration_seconds": 0.029119000071659684,
|
||||
"timestamp": "2025-06-01T00:34:24.484468",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "针对 DELETE http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/cd_geo_unit (状态码 200) 的响应体 conforms to the JSON schema."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-SECURITY-001",
|
||||
"test_case_name": "HTTPS Protocol Mandatory Verification",
|
||||
"test_case_severity": "严重",
|
||||
"status": "失败",
|
||||
"message": "API通过HTTP (http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/cd_geo_unit) 响应了成功的状态码 200,这违反了HTTPS强制策略。",
|
||||
"duration_seconds": 0.0279640001244843,
|
||||
"timestamp": "2025-06-01T00:34:24.512658",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-QUERY",
|
||||
"test_case_name": "Error Code 4001 - Query Parameter Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "失败",
|
||||
"message": "当查询参数 'id' (路径: 'id') 类型不匹配时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4001'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '26'.",
|
||||
"duration_seconds": 0.02449787501245737,
|
||||
"timestamp": "2025-06-01T00:34:24.537289",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 26,
|
||||
"message": "mollit Duis",
|
||||
"data": true
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4001",
|
||||
"mismatched_param": "id"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-BODY",
|
||||
"test_case_name": "Error Code 4001 - Request Body Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "失败",
|
||||
"message": "当请求体字段 'version' 类型不匹配时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4001'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '63'.",
|
||||
"duration_seconds": 0.02469349978491664,
|
||||
"timestamp": "2025-06-01T00:34:24.562116",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 63,
|
||||
"message": "fugiat eu tempor",
|
||||
"data": false
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4001",
|
||||
"mismatched_field": "body.version"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-BODY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Request Body Field Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "通过",
|
||||
"message": "跳过测试:在API规范中未找到合适的必填请求体字段用于移除测试。",
|
||||
"duration_seconds": 0.025086957961320877,
|
||||
"timestamp": "2025-06-01T00:34:24.587350",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "跳过测试:在API规范中未找到合适的必填请求体字段用于移除测试。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-QUERY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Query Parameter Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "失败",
|
||||
"message": "当移除必填查询参数 'id' 时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4003'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '73'.",
|
||||
"duration_seconds": 0.037851457949727774,
|
||||
"timestamp": "2025-06-01T00:34:24.625365",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 73,
|
||||
"message": "ullamco occaecat sit cupidatat Excepteur",
|
||||
"data": true
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4003",
|
||||
"removed_param": "query.id"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"endpoint_id": "POST /api/dms/{dms_instance_code}/v1/cd_geo_unit",
|
||||
"endpoint_name": "地质单元数据添加",
|
||||
"overall_status": "失败",
|
||||
"duration_seconds": 5.622572,
|
||||
"start_time": "2025-06-01T00:34:24.625494",
|
||||
"end_time": "2025-06-01T00:34:30.248066",
|
||||
"executed_test_cases": [
|
||||
{
|
||||
"test_case_id": "TC-STATUS-001",
|
||||
"test_case_name": "基本状态码 200 检查",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "响应状态码为 200,符合预期 200。",
|
||||
"duration_seconds": 5.46320699993521,
|
||||
"timestamp": "2025-06-01T00:34:30.090080",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "响应状态码为 200,符合预期 200。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-CORE-FUNC-001",
|
||||
"test_case_name": "Response Body JSON Schema Validation",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "Schema验证步骤完成(未发现问题,或schema不适用/未为此响应定义)。",
|
||||
"duration_seconds": 0.02542745810933411,
|
||||
"timestamp": "2025-06-01T00:34:30.115690",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "Schema验证步骤完成(未发现问题,或schema不适用/未为此响应定义)。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-SECURITY-001",
|
||||
"test_case_name": "HTTPS Protocol Mandatory Verification",
|
||||
"test_case_severity": "严重",
|
||||
"status": "失败",
|
||||
"message": "API通过HTTP (http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/cd_geo_unit) 响应了成功的状态码 200,这违反了HTTPS强制策略。",
|
||||
"duration_seconds": 0.023582458030432463,
|
||||
"timestamp": "2025-06-01T00:34:30.139370",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-QUERY",
|
||||
"test_case_name": "Error Code 4001 - Query Parameter Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "通过",
|
||||
"message": "跳过测试:在查询参数中未找到合适的字段来测试类型不匹配。",
|
||||
"duration_seconds": 0.02305808407254517,
|
||||
"timestamp": "2025-06-01T00:34:30.162526",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "跳过测试:在查询参数中未找到合适的字段来测试类型不匹配。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-BODY",
|
||||
"test_case_name": "Error Code 4001 - Request Body Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "失败",
|
||||
"message": "当请求体字段 'version' 类型不匹配时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4001'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '100'.",
|
||||
"duration_seconds": 0.02860183292068541,
|
||||
"timestamp": "2025-06-01T00:34:30.191222",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 100,
|
||||
"message": "ullamco sunt Duis",
|
||||
"data": false
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4001",
|
||||
"mismatched_field": "body.version"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-BODY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Request Body Field Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "失败",
|
||||
"message": "当移除必填请求体字段 'data.0.bsflag' 时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4003'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '24'.",
|
||||
"duration_seconds": 0.030035334173589945,
|
||||
"timestamp": "2025-06-01T00:34:30.221409",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 24,
|
||||
"message": "tempor exercitation occaecat laboris ea",
|
||||
"data": false
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4003",
|
||||
"removed_field": "body.data.0.bsflag"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-QUERY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Query Parameter Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "通过",
|
||||
"message": "跳过测试:在API规范中未找到合适的必填查询参数用于移除测试。",
|
||||
"duration_seconds": 0.026296500116586685,
|
||||
"timestamp": "2025-06-01T00:34:30.247916",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "跳过测试:在API规范中未找到合适的必填查询参数用于移除测试。"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"endpoint_id": "GET /api/dms/{dms_instance_code}/v1/cd_geo_unit/{version}/{id}",
|
||||
"endpoint_name": "地质单元查询详情",
|
||||
"overall_status": "失败",
|
||||
"duration_seconds": 7.815613,
|
||||
"start_time": "2025-06-01T00:34:30.248238",
|
||||
"end_time": "2025-06-01T00:34:38.063851",
|
||||
"executed_test_cases": [
|
||||
{
|
||||
"test_case_id": "TC-STATUS-001",
|
||||
"test_case_name": "基本状态码 200 检查",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "响应状态码为 200,符合预期 200。",
|
||||
"duration_seconds": 7.642308250069618,
|
||||
"timestamp": "2025-06-01T00:34:37.891148",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "响应状态码为 200,符合预期 200。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-CORE-FUNC-001",
|
||||
"test_case_name": "Response Body JSON Schema Validation",
|
||||
"test_case_severity": "严重",
|
||||
"status": "通过",
|
||||
"message": "针对 GET http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/cd_geo_unit/1.0.0/example_id (状态码 200) 的响应体 conforms to the JSON schema.",
|
||||
"duration_seconds": 0.025693500181660056,
|
||||
"timestamp": "2025-06-01T00:34:37.916967",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "针对 GET http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/cd_geo_unit/1.0.0/example_id (状态码 200) 的响应体 conforms to the JSON schema."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-SECURITY-001",
|
||||
"test_case_name": "HTTPS Protocol Mandatory Verification",
|
||||
"test_case_severity": "严重",
|
||||
"status": "失败",
|
||||
"message": "API通过HTTP (http://127.0.0.1:4523/m1/6389742-6086420-default/api/dms/example_dms_instance_code/v1/cd_geo_unit/1.0.0/example_id) 响应了成功的状态码 200,这违反了HTTPS强制策略。",
|
||||
"duration_seconds": 0.027092833071947098,
|
||||
"timestamp": "2025-06-01T00:34:37.944155",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-QUERY",
|
||||
"test_case_name": "Error Code 4001 - Query Parameter Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "通过",
|
||||
"message": "跳过测试:在查询参数中未找到合适的字段来测试类型不匹配。",
|
||||
"duration_seconds": 0.03259037504903972,
|
||||
"timestamp": "2025-06-01T00:34:37.976836",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "跳过测试:在查询参数中未找到合适的字段来测试类型不匹配。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4001-BODY",
|
||||
"test_case_name": "Error Code 4001 - Request Body Type Mismatch Validation",
|
||||
"test_case_severity": "中",
|
||||
"status": "失败",
|
||||
"message": "当请求体字段 'isSearchCount' 类型不匹配时,期望API返回状态码在 [400, 422] 中,或返回4xx客户端错误且业务码为 '4001'. 实际收到状态码 200. 响应体中的业务码 ('code') 为 '82'.",
|
||||
"duration_seconds": 0.035141333006322384,
|
||||
"timestamp": "2025-06-01T00:34:38.012121",
|
||||
"validation_points": [
|
||||
{
|
||||
"status_code": 200,
|
||||
"response_body": {
|
||||
"code": 82,
|
||||
"message": "id ipsum tempor",
|
||||
"data": {
|
||||
"total": 63,
|
||||
"list": [
|
||||
{
|
||||
"dsid": "28",
|
||||
"dataRegion": "est id culpa dolore consequat",
|
||||
"gasReleaseMon": null,
|
||||
"gasReleaseYear": null,
|
||||
"releaseGasCum": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"expected_http_status_codes": [
|
||||
400,
|
||||
422
|
||||
],
|
||||
"expected_business_code": "4001",
|
||||
"mismatched_field": "body.isSearchCount"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-BODY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Request Body Field Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "通过",
|
||||
"message": "跳过测试:在API规范中未找到合适的必填请求体字段用于移除测试。",
|
||||
"duration_seconds": 0.0262297501321882,
|
||||
"timestamp": "2025-06-01T00:34:38.038437",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "跳过测试:在API规范中未找到合适的必填请求体字段用于移除测试。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"test_case_id": "TC-ERROR-4003-QUERY",
|
||||
"test_case_name": "Error Code 4003 - Missing Required Query Parameter Validation",
|
||||
"test_case_severity": "高",
|
||||
"status": "通过",
|
||||
"message": "跳过测试:在API规范中未找到合适的必填查询参数用于移除测试。",
|
||||
"duration_seconds": 0.02522541698999703,
|
||||
"timestamp": "2025-06-01T00:34:38.063766",
|
||||
"validation_points": [
|
||||
{
|
||||
"passed": true,
|
||||
"message": "跳过测试:在API规范中未找到合适的必填查询参数用于移除测试。"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user