This commit is contained in:
gongwenxin
2025-05-28 15:55:46 +08:00
parent f0cc525141
commit 936714242f
313 changed files with 345685 additions and 7847 deletions
-330
View File
@@ -1,330 +0,0 @@
# APITestCase 开发指南
本文档旨在指导开发人员如何创建和使用自定义的 `APITestCase` 类,以扩展 DDMS 合规性验证软件的测试能力。通过继承 `BaseAPITestCase`,您可以编写灵活且强大的 Python 代码来定义针对 API 的各种验证逻辑。
## 1. `APITestCase` 概述
`APITestCase` 是 DDMS 合规性验证软件中定义具体测试逻辑的核心单元。每个派生自 `BaseAPITestCase` 的类代表一个独立的测试场景或一组相关的检查点,例如验证特定的请求头、检查响应状态码、或确保响应体符合特定业务规则。
**核心理念:**
* **代码即测试**:使用 Python 的全部功能来定义复杂的测试逻辑,摆脱传统基于配置或简单规则的限制。
* **灵活性**:允许测试用例在 API 请求的各个阶段介入,包括请求数据的生成、请求发送前的预校验、以及响应接收后的深度验证。
* **可重用性与模块化**:常见的验证逻辑可以封装在辅助函数或基类中,方便在多个测试用例间共享。
在测试执行期间,测试编排器(`APITestOrchestrator`)会自动发现、加载并执行适用于当前 API 端点的所有已注册的 `APITestCase` 实例。
## 2. 如何创建自定义测试用例
创建一个新的测试用例涉及以下步骤:
1. **创建 Python 文件**:在指定的测试用例目录(例如 `custom_testcases/`)下创建一个新的 `.py` 文件。建议文件名能反映其测试内容,例如 `header_validation_tests.py`
2. **继承 `BaseAPITestCase`**:在文件中定义一个或多个类,使其继承自 `your_project.test_framework_core.BaseAPITestCase` (请替换为实际路径)。
3. **定义元数据**:在您的自定义测试用例类中,必须定义以下类属性:
* `id: str`: 测试用例的全局唯一标识符。建议使用前缀来分类,例如 `"TC-HEADER-001"`
* `name: str`: 人类可读的测试用例名称,例如 `"必要请求头 X-Tenant-ID 存在性检查"`
* `description: str`: 对测试用例目的和范围的详细描述。
* `severity: TestSeverity`: 测试用例的严重程度,使用 `TestSeverity` 枚举(例如 `TestSeverity.CRITICAL`, `TestSeverity.HIGH`, `TestSeverity.MEDIUM`, `TestSeverity.LOW`, `TestSeverity.INFO`)。
* `tags: List[str]`: 一个字符串列表,用于对测试用例进行分类和过滤,例如 `["header", "security", "core-functionality"]`
4. **可选:控制适用范围**:您可以选择性地定义以下类属性来限制测试用例的应用范围:
* `applicable_methods: Optional[List[str]]`: 一个 HTTP 方法字符串的列表(大写),例如 `["POST", "PUT"]`。如果定义了此属性,则该测试用例仅应用于具有这些方法的 API 端点。如果为 `None`(默认),则适用于所有方法。
* `applicable_paths_regex: Optional[str]`: 一个 Python 正则表达式字符串。如果定义了此属性,则该测试用例仅应用于其路径与此正则表达式匹配的 API 端点。如果为 `None`(默认),则适用于所有路径。
5. **实现验证逻辑**:重写 `BaseAPITestCase` 中一个或多个 `generate_*``validate_*` 方法来实现您的具体测试逻辑。
**示例骨架:**
```python
# In custom_testcases/my_custom_header_check.py
from your_project.test_framework_core import BaseAPITestCase, TestSeverity, ValidationResult, APIRequestContext, APIResponseContext # 替换为实际路径
import logging # 推荐为每个测试用例获取 logger
class MySpecificHeaderCheck(BaseAPITestCase):
# 1. 元数据
id = "TC-MYHEADER-001"
name = "自定义头部 My-Custom-Header 格式检查"
description = "验证请求中 My-Custom-Header 是否存在且格式为 UUID。"
severity = TestSeverity.MEDIUM
tags = ["custom", "header", "format"]
# 2. 可选:适用范围 (例如,仅用于 POST 请求)
applicable_methods = ["POST"]
# applicable_paths_regex = r"/api/v1/orders/.*" # 示例:仅用于特定路径模式
def __init__(self, endpoint_spec: dict, global_api_spec: dict):
super().__init__(endpoint_spec, global_api_spec)
# self.logger 在基类中已初始化为 logging.getLogger(f"testcase.{self.id}")
self.logger.info(f"测试用例 {self.id} 已针对端点 {self.endpoint_spec.get('path')} 初始化。")
# 3. 实现验证逻辑 (见下一节)
def generate_headers(self, current_headers: dict) -> dict:
# 示例:确保我们的自定义头存在,如果不存在则添加一个用于测试
if "My-Custom-Header" not in current_headers:
current_headers["My-Custom-Header"] = "default-test-uuid-value" # 实际应生成有效UUID
return current_headers
def validate_request_headers(self, headers: dict, request_context: APIRequestContext) -> list[ValidationResult]:
results = []
custom_header_value = headers.get("My-Custom-Header")
if not custom_header_value:
results.append(ValidationResult(passed=False, message="请求头缺少 'My-Custom-Header'"))
else:
# 假设有一个 is_valid_uuid 函数
# if not is_valid_uuid(custom_header_value):
# results.append(ValidationResult(passed=False, message=f"'My-Custom-Header' 的值 '{custom_header_value}' 不是有效的UUID格式。"))
# else:
results.append(ValidationResult(passed=True, message="'My-Custom-Header' 存在且格式初步检查通过。"))
return results
# ... 其他可能需要重写的方法 ...
```
## 3. `BaseAPITestCase` 详解
`BaseAPITestCase` 提供了一系列可以在子类中重写的方法,这些方法覆盖了 API 测试生命周期的不同阶段。
### 3.1 构造函数 (`__init__`)
```python
def __init__(self, endpoint_spec: Dict[str, Any], global_api_spec: Dict[str, Any]):
```
* 当测试编排器为某个 API 端点实例化您的测试用例时,会调用此构造函数。
* **参数**:
* `endpoint_spec: Dict[str, Any]`: 当前正在测试的 API 端点的详细定义。这些信息直接来自 YAPI/Swagger 解析器解析得到的该端点的具体规范,例如包含路径、方法、参数定义(路径参数、查询参数、请求头参数)、请求体 schema、响应 schema 等。您可以使用这些信息来指导您的测试逻辑,例如,了解哪些字段是必需的,它们的数据类型是什么等。
* `global_api_spec: Dict[str, Any]`: 完整的 API 规范文档(例如,整个 YAPI 导出的 JSON 数组或整个 Swagger JSON 对象)。这允许测试用例在需要时访问 API 规范的全局信息,比如全局定义、标签、分类等。
* **注意**: 基类 `__init__` 方法会初始化 `self.endpoint_spec`, `self.global_api_spec``self.logger`。如果您重写 `__init__`,请务必调用 `super().__init__(endpoint_spec, global_api_spec)`
### 3.2 请求生成与修改方法
这些方法在测试编排器构建 API 请求之前被调用,允许您动态地修改或生成请求的各个部分。这对于构造特定的测试场景(例如,发送无效数据、测试边界条件、注入特定测试值)非常有用。
对于每个 API 端点,测试编排器会先尝试根据 API 规范(YAPI/Swagger)生成一个"基线"的请求(包含必要的参数、基于 schema 的请求体等)。然后,您的测试用例的 `generate_*` 方法会被调用,并传入这个基线数据作为参数,您可以对其进行修改。
1. **`generate_query_params(self, current_query_params: Dict[str, Any]) -> Dict[str, Any]`**
* **何时调用**: 在确定请求的查询参数时。
* **输入**: `current_query_params` - 一个字典,包含测试编排器根据 API 规范(例如 `endpoint_spec['req_query']`)和可能的默认值生成的当前查询参数。
* **输出**: 您必须返回一个字典,该字典将作为最终发送请求时使用的查询参数。您可以添加、删除或修改 `current_query_params` 中的条目。
* **用途**: 注入特定的查询参数值,测试不同的过滤条件、分页参数组合等。
2. **`generate_headers(self, current_headers: Dict[str, str]) -> Dict[str, str]`**
* **何时调用**: 在确定请求头时。
* **输入**: `current_headers` - 一个字典,包含测试编排器生成的当前请求头(可能包含如 `Content-Type`, `Accept` 等默认头,以及 API 规范中定义的请求头)。
* **输出**: 您必须返回一个字典,作为最终的请求头。
* **用途**: 添加/修改认证令牌 (`Authorization`)、租户ID (`X-Tenant-ID`)、自定义测试头等。
3. **`generate_request_body(self, current_body: Optional[Any]) -> Optional[Any]`**
* **何时调用**: 在确定请求体时 (主要用于 `POST`, `PUT`, `PATCH` 等方法)。
* **输入**: `current_body` - 测试编排器根据 API 规范中的请求体 schema (例如 `endpoint_spec['req_body_other']` for YAPI JSON body, 或 Swagger requestBody schema) 生成的请求体。可能是字典/列表 (对于JSON),字符串或其他类型。
* **输出**: 您必须返回最终要发送的请求体。
* **用途**: 构造特定的请求体数据,例如:
* 发送缺少必填字段的数据。
* 发送类型不匹配的数据。
* 发送超出范围的数值。
* 注入用于测试特定业务逻辑的数据。
### 3.3 请求预校验方法
这些方法在 API 请求的各个部分(URL、头、体)完全构建完成之后,但在实际发送到服务器之前被调用。这允许您在请求发出前对其进行最终的静态检查。
每个预校验方法都应返回一个 `List[ValidationResult]`
1. **`validate_request_url(self, url: str, request_context: APIRequestContext) -> List[ValidationResult]`**
* **何时调用**: 请求的完整 URL 构建完毕后。
* **输入**:
* `url: str`: 最终构建的、将要发送的完整请求 URL。
* `request_context: APIRequestContext`: 包含当前请求的详细上下文信息(见 4.2 节)。
* **用途**: 检查 URL 格式是否符合规范(例如 RESTful 路径结构 `/api/{version}/{resource}`)、路径参数是否正确编码、查询参数是否符合命名规范(如全小写+下划线)等。
2. **`validate_request_headers(self, headers: Dict[str, str], request_context: APIRequestContext) -> List[ValidationResult]`**
* **何时调用**: 请求头完全确定后。
* **输入**:
* `headers: Dict[str, str]`: 最终将要发送的请求头。
* `request_context: APIRequestContext`: 当前请求的上下文。
* **用途**: 检查是否包含所有必要的请求头 (`X-Tenant-ID`, `Authorization`)、头部字段值是否符合特定格式或约定。
3. **`validate_request_body(self, body: Optional[Any], request_context: APIRequestContext) -> List[ValidationResult]`**
* **何时调用**: 请求体完全确定后。
* **输入**:
* `body: Optional[Any]`: 最终将要发送的请求体。
* `request_context: APIRequestContext`: 当前请求的上下文。
* **用途**: 对最终的请求体进行静态检查,例如,检查 JSON 结构是否与预期一致(不一定是严格的 schema 验证,因为那通常在 `generate_request_body` 或由框架处理,但可以做一些更具体的业务逻辑检查)。
### 3.4 响应验证方法
这是最核心的验证阶段,在从服务器接收到 API 响应后调用。
1. **`validate_response(self, response_context: APIResponseContext, request_context: APIRequestContext) -> List[ValidationResult]`**
* **何时调用**: 收到 API 响应后。
* **输入**:
* `response_context: APIResponseContext`: 包含 API 响应的详细上下文信息(见 4.3 节),如状态码、响应头、响应体内容等。
* `request_context: APIRequestContext`: 触发此响应的原始请求的上下文。
* **输出**: 返回一个 `List[ValidationResult]`,包含对该响应的所有验证点的结果。
* **用途**: 这是进行绝大多数验证的地方,例如:
* 检查 HTTP 状态码是否符合预期。
* 验证响应头是否包含特定字段及其值。
* 对响应体内容进行 JSON Schema 验证(可以调用框架提供的 `JSONSchemaValidator`)。
* 验证响应体中的具体数据是否符合业务规则。
* 检查错误响应的结构和错误码是否正确。
### 3.5 性能与附加检查方法 (可选)
1. **`check_performance(self, response_context: APIResponseContext, request_context: APIRequestContext) -> List[ValidationResult]`**
* **何时调用**: 收到 API 响应后,通常在主要的 `validate_response` 之后。
* **输入**: 与 `validate_response` 相同。
* **输出**: 返回一个 `List[ValidationResult]`
* **用途**: 执行与性能相关的检查,最常见的是检查 API 的响应时间 (`response_context.elapsed_time`) 是否在可接受的阈值内。
## 4. 核心辅助类
这些类是 `BaseAPITestCase` 的重要组成部分,用于传递信息和报告结果。
### 4.1 `ValidationResult`
```python
class ValidationResult:
def __init__(self, passed: bool, message: str, details: Optional[Dict[str, Any]] = None):
self.passed: bool # True 表示验证通过, False 表示失败
self.message: str # 对验证结果的描述性消息
self.details: Dict[str, Any] # 可选的字典,用于存储额外信息,如实际值、期望值、上下文等
```
* **用途**: 所有 `validate_*``check_*` 方法都应返回一个此对象的列表。每个对象代表一个具体的检查点。
* **示例**:
```python
results.append(ValidationResult(passed=True, message="状态码为 200 OK。"))
results.append(ValidationResult(
passed=False,
message=f"用户ID不匹配。期望: '{expected_id}', 实际: '{actual_id}'",
details={"expected": expected_id, "actual": actual_id}
))
```
### 4.2 `APIRequestContext`
```python
class APIRequestContext:
def __init__(self, method: str, url: str, path_params: Dict[str, Any],
query_params: Dict[str, Any], headers: Dict[str, str], body: Optional[Any]):
self.method: str # HTTP 方法 (e.g., "GET", "POST")
self.url: str # 完整的请求 URL
self.path_params: Dict[str, Any] # 从路径中解析出的参数及其值
self.query_params: Dict[str, Any]# 最终使用的查询参数
self.headers: Dict[str, str] # 最终使用的请求头
self.body: Optional[Any] # 最终使用的请求体
```
* **用途**: 在请求相关的钩子方法中提供关于已构建请求的全面信息。
### 4.3 `APIResponseContext`
```python
class APIResponseContext:
def __init__(self, status_code: int, headers: Dict[str, str],
json_content: Optional[Any], text_content: Optional[str],
elapsed_time: float, original_response: Any):
self.status_code: int # HTTP 响应状态码 (e.g., 200, 404)
self.headers: Dict[str, str] # 响应头
self.json_content: Optional[Any]# 如果响应是JSON且成功解析,则为解析后的对象 (字典或列表),否则为 None
self.text_content: Optional[str]# 原始响应体文本内容
self.elapsed_time: float # API 调用耗时 (从发送请求到收到完整响应头),单位:秒
self.original_response: Any # 底层 HTTP 库返回的原始响应对象 (例如 `requests.Response`),供高级用例使用
```
* **用途**: 在响应相关的钩子方法中提供关于收到的 API 响应的全面信息。
### 4.4 `TestSeverity` 枚举
```python
from enum import Enum
class TestSeverity(Enum):
CRITICAL = "严重"
HIGH = "高"
MEDIUM = "中"
LOW = "低"
INFO = "信息"
```
* **用途**: 用于定义测试用例的严重级别,方便报告和结果分析。
## 5. 日志记录
`BaseAPITestCase` 在其 `__init__` 方法中为每个测试用例实例初始化了一个标准的 Python logger
`self.logger = logging.getLogger(f"testcase.{self.id}")`
您可以在测试用例的任何方法中使用 `self.logger` 来输出调试信息、执行流程或遇到的问题。
**示例**:
```python
self.logger.info(f"正在为端点 {self.endpoint_spec['path']} 生成请求体...")
if error_condition:
self.logger.warning(f"在为 {self.endpoint_spec['title']} 处理数据时遇到警告: {error_condition}")
```
这些日志将由应用程序的整体日志配置进行管理。
## 6. 简单示例:检查状态码和响应时间
```python
# In custom_testcases/basic_response_checks.py
from your_project.test_framework_core import BaseAPITestCase, TestSeverity, ValidationResult, APIRequestContext, APIResponseContext
class StatusCode200Check(BaseAPITestCase):
id = "TC-STATUS-001"
name = "状态码 200 OK 检查"
description = "验证 API 是否成功响应并返回状态码 200。"
severity = TestSeverity.CRITICAL
tags = ["status_code", "smoke"]
# 此测试用例适用于所有端点,因此无需定义 applicable_methods 或 applicable_paths_regex
def validate_response(self, response_context: APIResponseContext, request_context: APIRequestContext) -> list[ValidationResult]:
results = []
if response_context.status_code == 200:
results.append(ValidationResult(passed=True, message="响应状态码为 200 OK。"))
else:
results.append(ValidationResult(
passed=False,
message=f"期望状态码 200,但收到 {response_context.status_code}。",
details={
"expected_status": 200,
"actual_status": response_context.status_code,
"response_body_sample": (response_context.text_content or "")[:200] # 包含部分响应体以帮助诊断
}
))
return results
class ResponseTimeCheck(BaseAPITestCase):
id = "TC-PERF-001"
name = "API 响应时间检查 (小于1秒)"
description = "验证 API 响应时间是否在 1000 毫秒以内。"
severity = TestSeverity.MEDIUM
tags = ["performance"]
MAX_RESPONSE_TIME_SECONDS = 1.0 # 1 秒
def check_performance(self, response_context: APIResponseContext, request_context: APIRequestContext) -> list[ValidationResult]:
results = []
elapsed_ms = response_context.elapsed_time * 1000
if response_context.elapsed_time <= self.MAX_RESPONSE_TIME_SECONDS:
results.append(ValidationResult(
passed=True,
message=f"响应时间 {elapsed_ms:.2f}ms,在阈值 {self.MAX_RESPONSE_TIME_SECONDS*1000:.0f}ms 以内。"
))
else:
results.append(ValidationResult(
passed=False,
message=f"响应时间过长: {elapsed_ms:.2f}ms。期望小于 {self.MAX_RESPONSE_TIME_SECONDS*1000:.0f}ms。",
details={"actual_ms": elapsed_ms, "threshold_ms": self.MAX_RESPONSE_TIME_SECONDS*1000}
))
return results
```
## 7. 最佳实践和注意事项
* **保持测试用例的单一职责**:尽量让每个 `APITestCase` 类专注于一个特定的验证目标或一小组紧密相关的检查点。这使得测试用例更易于理解、维护和调试。
* **清晰的命名**:为您的测试用例类、`id` 和 `name` 使用清晰、描述性的名称。
* **充分利用 `endpoint_spec`**:在测试逻辑中,参考 `self.endpoint_spec` 来了解 API 的预期行为、参数、schema 等,使您的测试更加精确。
* **详细的 `ValidationResult` 消息**:当验证失败时,提供足够详细的 `message` 和 `details`,以便快速定位问题。
* **考虑性能**:虽然灵活性是关键,但避免在测试用例中执行过于耗时的操作,除非是专门的性能测试。
* **错误处理**:在您的测试用例代码中妥善处理可能发生的异常,并使用 `self.logger` 记录它们。
* **可重用逻辑**:如果多个测试用例需要相似的逻辑(例如,解析特定的响应结构、生成特定的测试数据),考虑将这些逻辑提取到共享的辅助函数或一个共同的基类中(您的测试用例可以继承自这个中间基类,而这个中间基类继承自 `BaseAPITestCase`)。
* **逐步实现**:从简单的测试用例开始,逐步构建更复杂的验证逻辑。
通过遵循本指南,您将能够有效地利用 `APITestCase` 机制为您的 DDMS 合规性验证软件构建强大而灵活的自动化测试。
-172
View File
@@ -1,172 +0,0 @@
# Python 代码规则详解
## 概述
Python 代码规则是 DDMS 合规性验证软件中最灵活的规则类型,允许使用 Python 编写复杂的验证逻辑。与其他基于JSON结构的规则不同,Python 代码规则能够实现任何自定义逻辑,如复杂的数学计算、字符串处理、条件判断等。
## 规则结构
Python 代码规则由两部分组成:
1. **元数据文件** (JSON格式):包含规则的基本信息和配置参数
2. **代码文件** (Python格式):包含实际的验证逻辑代码
### 元数据文件格式
```json
{
"id": "rule-id",
"name": "规则名称",
"description": "规则描述",
"category": "PythonCode",
"version": "1.0.0",
"severity": "error",
"source": "Standard-2023",
"is_enabled": true,
"tags": ["tag1", "tag2"],
"target_type": "DataObject",
"target_identifier": "TargetName",
"allow_imports": true,
"allowed_modules": ["math", "re", "json", "datetime"],
"entry_function": "validate",
"expected_parameters": ["param1", "param2"],
"timeout": 5,
"code_file": "path/to/code/file.py"
}
```
### 主要字段说明
- **id**: 规则的唯一标识符
- **name**: 规则名称
- **description**: 规则功能描述
- **category**: 固定为 "PythonCode"
- **version**: 规则版本号
- **severity**: 规则严重级别,如 "error", "warning", "info"
- **is_enabled**: 规则是否启用
- **tags**: 用于分类和筛选的标签列表
- **target_type**: 规则适用的目标类型,如 "DataObject", "API", "Process"
- **target_identifier**: 具体目标的标识符,如 "Well", "Seismic"
- **allow_imports**: 是否允许导入外部模块
- **allowed_modules**: 允许导入的模块列表
- **entry_function**: 入口函数名(默认为 "validate"
- **expected_parameters**: 规则执行所需的参数列表
- **timeout**: 代码执行超时时间(秒)
- **code_file**: 外部Python代码文件的路径(相对于rules目录)
## 代码文件
代码文件应包含与 `entry_function` 字段指定的同名函数(默认是 "validate"),该函数作为验证逻辑的入口点。
### 代码文件示例
```python
"""
井坐标验证规则
此规则验证井的坐标是否在有效范围内,并检查与参考井的距离。
"""
import math
def is_valid_coordinate(lat, lon):
# 验证逻辑
return True
def calculate_distance(lat1, lon1, lat2, lon2):
# 计算距离的逻辑
return 0.0
def validate():
"""
验证入口函数
在这里实现完整的验证逻辑
"""
# 从全局命名空间获取参数
param1 = globals().get('param1')
# 执行验证逻辑
# ...
# 返回验证结果
return {
'is_valid': True,
'message': '验证通过',
'details': {
'additional_info': 'some value'
}
}
```
## 验证结果
验证函数应返回以下格式的结果:
1. **布尔值**:简单地表示验证成功或失败
2. **字典**:包含详细的验证结果,推荐格式如下:
```python
{
'is_valid': True/False, # 必需,表示验证结果
'message': '验证结果消息', # 可选,描述验证结果
'details': { ... } # 可选,包含详细信息的字典
}
```
## 安全限制
为了确保系统安全,Python 代码规则在执行时受到以下限制:
1. 只能导入明确允许的模块
2. 代码执行有超时限制
3. 无法访问文件系统、网络或系统命令
4. 在隔离的执行环境中运行
## 代码规则存储结构
推荐的存储结构如下:
```
rules/
python_code/
<rule-id>/
<version>.json # 元数据文件
<version>.py # Python代码文件
```
例如:
```
rules/
python_code/
well-coordinates-validation/
1.0.0.json
1.0.0.py
```
## 使用场景
Python 代码规则适用于以下场景:
1. **复杂的数值计算**:如坐标转换、距离计算、范围检查等
2. **字符串处理**:解析和验证具有特定格式的字符串
3. **条件逻辑**:需要多个条件组合的复杂判断
4. **时间处理**:日期和时间的验证和计算
5. **数据转换**:在验证前需要对数据进行转换或规范化
## 测试代码规则
可以使用提供的测试工具来验证规则的正确性:
```bash
python -m ddms_compliance_suite.test_executor.test_python_external_code
```
## 最佳实践
1. **代码注释**:添加详细的注释,特别是对于复杂的逻辑
2. **模块化**:将复杂逻辑拆分为多个小函数
3. **错误处理**:使用异常处理捕获可能的错误
4. **参数验证**:在函数开始时验证参数的有效性
5. **详细结果**:返回详细的验证结果,便于理解验证失败的原因
6. **版本管理**:为每个版本的规则创建单独的代码文件
-387
View File
@@ -1,387 +0,0 @@
# 规则库增强设计与用法指南
## 概述
DDMS合规性验证软件的规则库是整个系统的核心组件,用于存储、管理和执行各种验证规则。本文档介绍了规则库的增强设计,包括新增的规则类型、生命周期和作用域支持、YAML规则格式等特性,以及如何使用这些新功能。
## 增强特性
### 1. 规则生命周期
规则生命周期定义了规则在API测试流程中的适用阶段,使规则执行更加精确和高效。规则生命周期包括以下几个阶段:
- **请求准备阶段 (RequestPreparation)**: 在构建和发送API请求之前执行的规则,用于验证请求URL、请求头、请求参数等是否符合要求。
- **请求执行阶段 (RequestExecution)**: 在发送API请求过程中执行的规则,用于监控请求的执行过程。
- **响应验证阶段 (ResponseValidation)**: 在接收到API响应后执行的规则,用于验证响应状态码、响应头、响应体等是否符合要求。
- **后处理阶段 (PostValidation)**: 在完成响应验证后执行的规则,用于执行一些清理或记录工作。
- **任意阶段 (AnyStage)**: 不关注具体执行阶段的通用规则。
### 2. 规则作用域
规则作用域定义了规则针对的具体对象,使规则的应用更加精确。规则作用域包括以下几个类型:
- **请求URL (RequestURL)**: 规则验证请求的URL是否符合要求,如是否符合RESTful设计规范等。
- **请求头 (RequestHeaders)**: 规则验证请求头是否符合要求,如是否包含必要的认证信息等。
- **请求参数 (RequestParams)**: 规则验证请求参数是否符合要求,如参数格式、必填项等。
- **请求体 (RequestBody)**: 规则验证请求体是否符合要求,如必要的字段、格式等。
- **响应状态码 (ResponseStatus)**: 规则验证响应状态码是否符合要求,如是否为200、404等特定状态码。
- **响应头 (ResponseHeaders)**: 规则验证响应头是否符合要求,如是否包含跨域头等。
- **响应体 (ResponseBody)**: 规则验证响应体是否符合要求,如必要的字段、格式等。
- **响应时间 (ResponseTime)**: 规则验证API响应时间是否在允许的范围内。
- **安全性 (Security)**: 规则验证API安全相关的要求,如是否使用HTTPS、是否包含认证信息等。
- **性能 (Performance)**: 规则验证API性能相关的要求,如响应时间、资源消耗等。
- **任意作用域 (AnyScope)**: 不关注具体作用域的通用规则。
### 3. 新增规则类型
为了满足不同场景的验证需求,增强了以下规则类型:
- **性能规则 (PerformanceRule)**: 用于验证API性能相关的指标,如响应时间、吞吐量等。
- **安全规则 (SecurityRule)**: 用于验证API安全相关的要求,如HTTPS强制、认证授权等。
- **RESTful设计规则 (RESTfulDesignRule)**: 用于验证API URL设计是否符合RESTful规范。
- **错误处理规则 (ErrorHandlingRule)**: 用于验证API错误响应是否符合标准格式和处理方式。
### 4. YAML规则格式
为了提高规则的可读性和可维护性,增加了对YAML格式规则的支持。YAML格式的规则可以直接嵌入Python代码,实现更灵活的验证逻辑。
## 规则示例
### 性能规则示例
```yaml
id: response-time-threshold
name: 响应时间阈值规则
description: 验证API响应时间是否在允许的范围内
category: Performance
version: 1.0.0
severity: warning
is_enabled: true
tags:
- performance
- response-time
target_type: APIResponse
lifecycle: ResponseValidation
scope: ResponseTime
threshold: 500 # 毫秒
metric: response_time
unit: ms
code: |
def validate(context):
response = context.get('api_response')
if not response:
return {'is_valid': False, 'message': '缺少API响应对象'}
response_time = response.elapsed_time * 1000 # 转换为毫秒
threshold = context.get('threshold', 500) # 默认500毫秒
if response_time > threshold:
return {
'is_valid': False,
'message': f'响应时间 {response_time:.2f}ms 超过阈值 {threshold}ms',
'details': {
'actual_time': response_time,
'threshold': threshold,
'unit': 'ms'
}
}
return {
'is_valid': True,
'message': f'响应时间 {response_time:.2f}ms 在阈值 {threshold}ms 内',
'details': {
'actual_time': response_time,
'threshold': threshold,
'unit': 'ms'
}
}
```
### 安全规则示例
```yaml
id: https-only-rule
name: HTTPS强制使用规则
description: 验证API是否只使用HTTPS协议,确保通信安全
category: Security
version: 1.0.0
severity: error
is_enabled: true
tags:
- security
- https
- encryption
target_type: APIRequest
lifecycle: RequestPreparation
scope: Security
check_type: transport_security
expected_value: https
code: |
def validate(context):
request = context.get('api_request')
if not request:
return {'is_valid': False, 'message': '缺少API请求对象'}
url = str(request.url)
if not url.startswith('https://'):
return {
'is_valid': False,
'message': 'API请求必须使用HTTPS协议',
'details': {
'current_url': url,
'expected_protocol': 'https'
}
}
return {
'is_valid': True,
'message': 'API请求使用了HTTPS协议',
'details': {
'url': url
}
}
```
### RESTful设计规则示例
```yaml
id: restful-url-pattern
name: RESTful URL设计规则
description: 验证API URL是否符合RESTful设计规范
category: APIDesign
version: 1.0.0
severity: warning
is_enabled: true
tags:
- restful
- api-design
- url-pattern
target_type: APIRequest
lifecycle: RequestPreparation
scope: RequestURL
design_aspect: URL设计
pattern: "^/api/v\\d+/[a-z0-9-]+(/[a-z0-9-]+)*$"
code: |
import re
def validate(context):
request = context.get('api_request')
if not request:
return {'is_valid': False, 'message': '缺少API请求对象'}
url = str(request.url)
# 解析URL,获取路径部分
from urllib.parse import urlparse
parsed_url = urlparse(url)
path = parsed_url.path
# 使用正则表达式验证路径
pattern = context.get('pattern', "^/api/v\\d+/[a-z0-9-]+(/[a-z0-9-]+)*$")
if not re.match(pattern, path):
return {
'is_valid': False,
'message': 'API URL不符合RESTful设计规范',
'details': {
'current_path': path,
'expected_pattern': pattern,
'suggestion': '路径应该遵循 /api/v{version}/{资源}[/{id}] 格式'
}
}
return {
'is_valid': True,
'message': 'API URL符合RESTful设计规范',
'details': {
'path': path
}
}
```
### 错误处理规则示例
```yaml
id: standard-error-response
name: 标准错误响应格式规则
description: 验证API错误响应是否符合标准格式
category: ErrorHandling
version: 1.0.0
severity: warning
is_enabled: true
tags:
- error-handling
- response-format
target_type: APIResponse
lifecycle: ResponseValidation
scope: ResponseBody
error_code: "*" # 匹配所有错误码
expected_status: -1 # 不验证状态码
code: |
def validate(context):
response = context.get('api_response')
if not response:
return {'is_valid': False, 'message': '缺少API响应对象'}
# 只检查4xx和5xx状态码的响应
if response.status_code < 400:
return {'is_valid': True, 'message': '非错误响应,跳过验证'}
# 确保响应包含JSON内容
if not response.json_content:
return {
'is_valid': False,
'message': '错误响应不是有效的JSON格式',
'details': {
'status_code': response.status_code,
'content_type': response.headers.get('Content-Type', '未知')
}
}
# 检查错误响应的必要字段
required_fields = ['code', 'message']
missing_fields = [field for field in required_fields if field not in response.json_content]
if missing_fields:
return {
'is_valid': False,
'message': '错误响应缺少必要字段',
'details': {
'missing_fields': missing_fields,
'required_fields': required_fields,
'response': response.json_content
}
}
return {
'is_valid': True,
'message': '错误响应符合标准格式',
'details': {
'status_code': response.status_code,
'error_code': response.json_content.get('code'),
'error_message': response.json_content.get('message')
}
}
```
## 使用方法
### 1. 创建规则
可以通过以下两种方式创建规则:
1. **编程方式创建**:通过实例化规则类来创建规则对象,然后使用规则库的`save_rule`方法保存。
```python
from ddms_compliance_suite.models.rule_models import PerformanceRule, RuleCategory, TargetType, RuleLifecycle, RuleScope
# 创建性能规则
performance_rule = PerformanceRule(
id="response-time-max-500ms",
name="响应时间不超过500毫秒",
description="验证API响应时间不超过500毫秒",
category=RuleCategory.PERFORMANCE,
severity="warning",
target_type=TargetType.API_RESPONSE,
lifecycle=RuleLifecycle.RESPONSE_VALIDATION,
scope=RuleScope.RESPONSE_TIME,
threshold=500,
metric="response_time",
unit="ms"
)
# 保存规则
rule_repository.save_rule(performance_rule)
```
2. **YAML文件创建**:将规则定义为YAML文件,存放在规则库的目录结构中。
YAML规则文件存放路径: `rules/yaml_rules/{category}/{rule_id}/{version}.yaml`
### 2. 查询规则
可以使用规则库的`query_rules`方法查询规则,支持按规则类别、目标类型、生命周期、作用域等条件筛选。
```python
from ddms_compliance_suite.models.rule_models import RuleQuery, RuleCategory, TargetType, RuleLifecycle, RuleScope
# 查询所有API响应验证阶段的性能规则
query = RuleQuery(
category=RuleCategory.PERFORMANCE,
target_type=TargetType.API_RESPONSE,
lifecycle=RuleLifecycle.RESPONSE_VALIDATION,
scope=RuleScope.RESPONSE_TIME,
is_enabled=True
)
rules = rule_repository.query_rules(query)
print(f"找到 {len(rules)} 条规则")
```
### 3. 执行规则
可以使用规则执行引擎的`execute_rule`方法执行单个规则,或使用`execute_rules_for_lifecycle`方法执行特定生命周期阶段的所有规则。
```python
from ddms_compliance_suite.rule_executor.executor import RuleExecutor
# 创建规则执行引擎
executor = RuleExecutor(rule_repository)
# 执行单个规则
result = executor.execute_rule(rule, context)
print(f"规则 '{result.rule_name}' 结果: {'通过' if result.is_valid else '失败'} - {result.message}")
# 执行特定生命周期阶段的所有规则
results = executor.execute_rules_for_lifecycle(RuleLifecycle.RESPONSE_VALIDATION, context)
for result in results:
print(f"规则 '{result.rule_name}' 结果: {'通过' if result.is_valid else '失败'} - {result.message}")
```
### 4. 在测试中使用规则
可以在API测试流程中集成规则验证,以确保API请求和响应符合规范要求。
```python
from ddms_compliance_suite.api_caller.caller import APICaller, APIRequest
from ddms_compliance_suite.rule_executor.executor import RuleExecutor
# 创建API调用器
api_caller = APICaller()
# 创建API请求
request = APIRequest(
method="GET",
url="https://api.example.com/api/v1/users/123",
headers={"Content-Type": "application/json"}
)
# 执行请求准备阶段的规则
context = {"api_request": request}
prep_results = executor.execute_rules_for_lifecycle(RuleLifecycle.REQUEST_PREPARATION, context)
for result in prep_results:
print(f"规则 '{result.rule_name}' 结果: {'通过' if result.is_valid else '失败'} - {result.message}")
# 发送API请求
response = api_caller.call_api(request)
# 执行响应验证阶段的规则
context["api_response"] = response
resp_results = executor.execute_rules_for_lifecycle(RuleLifecycle.RESPONSE_VALIDATION, context)
for result in resp_results:
print(f"规则 '{result.rule_name}' 结果: {'通过' if result.is_valid else '失败'} - {result.message}")
```
## 最佳实践
1. **合理组织规则**:按照规则类别、生命周期和作用域组织规则,使规则库结构清晰。
2. **使用标签**:为规则添加标签,方便按照特定主题或功能筛选规则。
3. **合理设置优先级**:为规则设置合理的严重性级别,以便于区分重要规则和次要规则。
4. **编写清晰的规则描述**:为规则提供清晰的描述,使其他开发者能够理解规则的用途和行为。
5. **使用YAML格式**:对于复杂的验证逻辑,优先使用YAML格式的规则,便于维护和调试。
6. **避免硬编码**:在规则中避免硬编码具体的验证标准,而是通过规则属性来配置。
7. **定期维护规则库**:随着API的演进,定期更新和维护规则库,确保规则始终有效。
## 结论
规则库的增强设计为API测试提供了更强大、更灵活的验证能力,使得DDMS合规性验证软件能够更精确地验证API接口的行为,确保其符合平台定义的数据共享标准和技术规范。通过合理组织和使用规则,可以显著提高API测试的效率和质量。
-141
View File
@@ -1,141 +0,0 @@
# DDMS合规性验证框架项目总结
## 项目概述
DDMS合规性验证框架(DDMS Compliance Framework)是一个专门为验证API接口合规性而设计的软件框架。该框架能够自动生成API测试用例,执行API调用,验证API响应,并根据预定义的规则检查API是否符合DDMS平台的技术规范和数据共享标准。
## 项目目标
1. **自动化API测试**:实现API测试用例的自动生成和执行,提高测试效率。
2. **规范性验证**:确保API接口符合REST风格设计规范。
3. **性能监控**:监控API响应时间和资源使用,确保API性能符合要求。
4. **安全性检查**:验证API实现了必要的安全措施,如HTTPS传输和认证授权。
5. **灵活的规则配置**:支持多种规则类型和规则定义方式,以适应不同的验证需求。
6. **可扩展性**:框架设计具有良好的可扩展性,便于添加新的验证规则和功能。
## 系统架构
### 核心组件
1. **API测试生成器 (API Test Generator)**
- 解析API定义:从YAPI和Swagger文件中解析API定义。
- 生成测试用例:基于API定义自动生成测试用例。
- 支持多种HTTP方法:GET、POST、PUT、DELETE等。
- 处理各种参数类型:路径参数、查询参数、请求体等。
2. **API调用器 (API Caller)**
- 构建API请求:根据测试用例构建HTTP请求。
- 发送请求:向目标服务器发送HTTP请求。
- 处理响应:接收并处理HTTP响应。
- 支持各种请求类型:支持JSON、XML、表单等格式的请求。
3. **规则库 (Rule Repository)**
- 存储规则:管理各种验证规则。
- 规则分类:支持按类别、生命周期、作用域等分类规则。
- 规则查询:提供灵活的规则查询接口。
- YAML规则支持:支持使用YAML格式定义规则和嵌入Python验证逻辑。
4. **规则执行引擎 (Rule Executor)**
- 执行规则:在API测试流程中执行相应的规则。
- 结果收集:收集规则执行结果。
- 结果分析:分析规则执行结果,生成验证报告。
- 支持各种规则类型:性能规则、安全规则、设计规则等。
5. **测试协调器 (Test Orchestrator)**
- 协调测试流程:管理整个API测试的流程。
- 集成各个组件:将API测试生成器、API调用器、规则库和规则执行引擎集成起来。
- 结果汇总:汇总各个阶段的测试结果。
- 生成报告:生成详细的API测试报告。
### 流程说明
1. **测试准备阶段**
- 解析API定义,提取API信息。
- 生成API测试用例。
- 根据测试用例构建API请求。
- 执行请求准备阶段的规则验证。
2. **测试执行阶段**
- 发送API请求到目标服务器。
- 接收API响应。
- 执行请求执行阶段的规则验证。
3. **结果验证阶段**
- 验证API响应是否符合预期。
- 执行响应验证阶段的规则验证。
- 收集验证结果。
4. **报告生成阶段**
- 汇总各个阶段的验证结果。
- 生成详细的测试报告。
- 执行后处理阶段的规则验证。
## 技术特点
### 1. 规则生命周期支持
框架引入了规则生命周期的概念,使规则执行更加精确和高效:
- **请求准备阶段 (RequestPreparation)**:在构建和发送API请求之前执行的规则,用于验证请求URL、请求头、请求参数等是否符合要求。
- **请求执行阶段 (RequestExecution)**:在发送API请求过程中执行的规则,用于监控请求的执行过程。
- **响应验证阶段 (ResponseValidation)**:在接收到API响应后执行的规则,用于验证响应状态码、响应头、响应体等是否符合要求。
- **后处理阶段 (PostValidation)**:在完成响应验证后执行的规则,用于执行一些清理或记录工作。
### 2. 规则作用域支持
框架引入了规则作用域的概念,使规则的应用更加精确:
- **请求URL (RequestURL)**:规则验证请求的URL是否符合要求,如是否符合RESTful设计规范等。
- **请求头 (RequestHeaders)**:规则验证请求头是否符合要求,如是否包含必要的认证信息等。
- **响应状态码 (ResponseStatus)**:规则验证响应状态码是否符合要求,如是否为200、404等特定状态码。
- **响应时间 (ResponseTime)**:规则验证API响应时间是否在允许的范围内。
- **安全性 (Security)**:规则验证API安全相关的要求,如是否使用HTTPS、是否包含认证信息等。
### 3. 多种规则类型
框架支持多种规则类型,以满足不同场景的验证需求:
- **性能规则 (PerformanceRule)**:用于验证API性能相关的指标,如响应时间、吞吐量等。
- **安全规则 (SecurityRule)**:用于验证API安全相关的要求,如HTTPS强制、认证授权等。
- **RESTful设计规则 (RESTfulDesignRule)**:用于验证API URL设计是否符合RESTful规范。
- **错误处理规则 (ErrorHandlingRule)**:用于验证API错误响应是否符合标准格式和处理方式。
### 4. YAML规则格式支持
框架支持使用YAML格式定义规则,并可以在YAML中嵌入Python验证逻辑,提高规则的可读性和可维护性。
### 5. 自动生成测试数据
框架能够基于API定义自动生成测试数据,包括路径参数、查询参数、请求体等,减少手动编写测试数据的工作量。
## 项目成果
1. **API测试生成器**:成功实现了从YAPI和Swagger文件中自动生成API测试用例的功能,支持各种HTTP方法和参数类型。
2. **规则库增强**:实现了规则生命周期、规则作用域、多种规则类型和YAML规则格式的支持,使规则库更加强大和灵活。
3. **规则执行引擎**:实现了规则执行引擎,能够在API测试流程中执行各种规则,并收集和分析规则执行结果。
4. **示例规则实现**:实现了多种类型的规则示例,包括性能规则、安全规则、RESTful设计规则和错误处理规则等。
5. **演示脚本**:实现了演示脚本,用于展示框架的功能和用法,包括规则执行演示和API测试演示等。
6. **完善的文档**:编写了详细的文档,包括项目总结、规则库增强设计与用法指南、API测试框架使用说明等。
## 未来展望
1. **规则库扩展**:继续扩展规则库,添加更多类型的规则和验证逻辑。
2. **界面开发**:开发Web界面,方便用户管理规则、执行测试和查看测试报告。
3. **报告优化**:优化测试报告的格式和内容,提供更丰富的图表和分析结果。
4. **集成CI/CD**:将框架集成到CI/CD流程中,实现API测试的自动化执行和报告生成。
5. **数据驱动**:支持数据驱动测试,使测试用例更加灵活和全面。
6. **负载测试**:增加负载测试功能,验证API在高并发情况下的性能和稳定性。
## 总结
DDMS合规性验证框架是一个强大而灵活的API测试和验证工具,它通过自动化测试和规则验证,确保API接口符合DDMS平台的技术规范和数据共享标准。该框架的设计和实现充分考虑了可扩展性和灵活性,能够满足各种API测试和验证需求。