<think>好的,我现在需要帮用户设计一个基于Python的接口测试框架,对接Swagger,用Excel维护测试用例,测试结果存到MySQL。首先,我得理清楚各个组件和实现步骤。
用户的需求很明确,四个主要部分:对接Swagger、Excel管理用例、MySQL存储结果、Python实现。我得先考虑每个部分怎么实现,再整合起来。
首先,对接Swagger。Swagger通常提供OpenAPI文档,一般是JSON格式的。我需要用Python读取这个文档,解析里面的接口信息,比如路径、方法、参数等。可能需要用requests库来获取Swagger的JSON数据,然后解析出接口列表。这部分可能需要处理不同的版本,比如Swagger 2.0和OpenAPI 3.0,结构可能不同,得考虑兼容性。
然后是Excel管理测试用例。用户可能希望每个接口有多个测试用例,包括各种参数组合、预期结果等。用openpyxl库来处理Excel文件比较合适。需要设计Excel的格式,比如每个sheet对应一个接口,或者用特定的列来存储请求方法、URL、参数、预期状态码、预期响应内容等。可能需要先定义好模板,用户按照模板填写用例。
接下来是测试执行部分。需要根据用例中的请求方法(GET、POST等)发送HTTP请求。用requests库发送请求比较方便。要考虑如何处理不同的参数类型,比如query参数、form-data、JSON body等。还需要处理动态参数,比如可能需要从之前的响应中提取token,用于后续请求的鉴权。这可能需要用到参数化或者变量替换的功能。
然后是结果保存到MySQL。需要设计数据库表结构,比如测试报告表,包含用例ID、执行时间、请求数据、响应数据、断言结果、执行状态等。使用pymysql库或者SQLAlchemy来操作数据库。需要考虑并发执行时的连接管理,以及如何高效地插入大量测试结果。
框架的整体结构可能需要模块化,比如将Swagger解析、Excel读取、请求发送、结果存储分成不同的模块。还可以考虑加入日志记录、测试报告生成(比如HTML报告),以及异常处理机制。
可能遇到的挑战包括Swagger文档的解析复杂性,特别是不同版本的差异;Excel用例的灵活性和易用性之间的平衡;测试用例的参数化需求,比如动态生成数据;还有测试结果的汇总和分析功能。此外,如何处理接口之间的依赖关系,比如一个接口的响应作为另一个接口的输入,这也是需要考虑的。
需要确认用户是否需要持续集成(CI)的支持,比如集成到Jenkins或者GitHub Actions中,但这可能超出当前范围。另外,是否需要支持数据驱动测试,即同一个用例多组数据运行,这可能会影响Excel结构的设计。
最后,代码结构的大致思路是:主程序读取Swagger生成接口配置,读取Excel中的测试用例,依次执行每个用例,发送请求,进行断言,记录结果到MySQL。同时需要处理异常情况,比如网络错误、断言失败等,并确保结果准确记录。
可能需要先写一个原型,验证各个模块的功能,再逐步完善。比如先实现Swagger解析和Excel读取,再整合请求发送和数据库存储。测试过程中要确保各模块的兼容性和稳定性,特别是处理各种边界情况和异常输入。</think>以下是分步实现的框架设计方案:
$$框架架构图$$
```mermaid
graph TD
A[Swagger解析模块] --> B[测试用例管理]
C[Excel数据源] --> B
B --> D[测试执行引擎]
D --> E[MySQL结果存储]
E --> F[测试报告生成]
```
一、核心模块设计
1. **Swagger对接模块**
```python
import requests
from openapi_spec_validator import validate_spec
class SwaggerParser:
def __init__(self, swagger_url):
self.swagger_url = swagger_url
def get_apis(self):
"""获取接口清单"""
response = requests.get(self.swagger_url)
spec_dict = response.json()
validate_spec(spec_dict) # 验证OpenAPI规范
apis = []
for path, methods in spec_dict['paths'].items():
for method, details in methods.items():
apis.append({
'path': path,
'method': method.upper(),
'parameters': details.get('parameters', []),
'responses': details['responses']
})
return apis
```
2. **Excel测试用例管理**
```
测试用例.xlsx结构示例:
-----------------------------------------
| 用例ID | 接口路径 | 方法 | 请求参数 | 预期状态码 | 预期响应 | 前置条件 |
-----------------------------------------
| TC001 | /api/login | POST | {"username":"admin","password":"123456"} | 200 | {"code":0} | - |
```
```python
from openpyxl import load_workbook
class ExcelManager:
def __init__(self, file_path):
self.wb = load_workbook(file_path)
def read_cases(self):
cases = []
for sheet in self.wb.worksheets:
for row in sheet.iter_rows(min_row=2, values_only=True):
case = {
"case_id": row[0],
"path": row[1],
"method": row[2],
"params": self._parse_params(row[3]),
"expected_status": row[4],
"expected_response": row[5],
"precondition": row[6]
}
cases.append(case)
return cases
def _parse_params(self, param_str):
"""将JSON字符串转换为Python字典"""
return json.loads(param_str)
```
3. **测试执行引擎
```python
import requests
from requests.adapters import HTTPAdapter
class TestRunner:
def __init__(self):
self.session = requests.Session()
self.session.mount('http://', HTTPAdapter(max_retries=3))
def execute_case(self, case):
try:
# 处理动态参数(如从前置条件获取token)
if case['precondition']:
self._handle_precondition(case['precondition'])
response = self.session.request(
method=case['method'],
url=f"{config.BASE_URL}{case['path']}",
json=case['params']
)
# 断言验证
assert_result = {
"status_code": response.status_code == case['expected_status'],
"response_body": self._compare_json(
response.json(),
case['expected_response']
)
}
return response, assert_result
except Exception as e:
return None, {"error": str(e)}
```
4. **MySQL结果存储
```sql
-- 建表语句
CREATE TABLE test_results (
id INT AUTO_INCREMENT PRIMARY KEY,
case_id VARCHAR(50) NOT NULL,
execute_time DATETIME DEFAULT CURRENT_TIMESTAMP,
request_data TEXT,
response_data TEXT,
assertions JSON,
is_success BOOLEAN,
duration FLOAT
);
```
```python
import pymysql
from datetime import datetime
class MySQLReporter:
def __init__(self):
self.conn = pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test_report'
)
def save_result(self, case, response, assert_result):
with self.conn.cursor() as cursor:
sql = """INSERT INTO test_results
(case_id, request_data, response_data, assertions, is_success)
VALUES (%s, %s, %s, %s, %s)"""
cursor.execute(sql, (
case['case_id'],
json.dumps(case['params']),
response.text if response else '',
json.dumps(assert_result),
all(assert_result.values())
))
self.conn.commit()
```
二、执行流程
```mermaid
sequenceDiagram
participant S as Swagger
participant F as Framework
participant E as Excel
participant M as MySQL
F->>S: 获取API清单
S-->>F: 返回接口定义
F->>E: 读取测试用例
E-->>F: 返回用例数据
loop 执行测试
F->>F: 发送HTTP请求
F->>F: 执行断言验证
F->>M: 存储测试结果
end
F->>F: 生成测试报告
```
三、扩展优化建议
1. **动态参数处理**:使用`${variable}`语法支持参数化
```python
# 在请求发送前替换变量
def replace_variables(data, variables):
pattern = re.compile(r'\${(.*?)}')
return pattern.sub(lambda m: str(variables.get(m.group(1), '')), data)
```
2. **自动化断言机制**:
```python
def smart_assert(expected, actual):
"""智能断言,支持类型匹配和模糊匹配"""
if isinstance(expected, dict):
for k, v in expected.items():
assert k in actual, f"缺少字段 {k}"
smart_assert(v, actual[k])
elif isinstance(expected, list):
assert len(expected) == len(actual)
for i, item in enumerate(expected):
smart_assert(item, actual[i])
else:
assert expected == actual
```
3. **异步执行优化**:
```python
import asyncio
import aiohttp
async def async_execute(case):
async with aiohttp.ClientSession() as session:
async with session.request(
method=case['method'],
url=case['url'],
json=case['params']
) as response:
return await response.json()
```
四、部署建议
1. 配置文件示例(config.py):
```python
class Config:
SWAGGER_URL = "http://api.example.com/v2/swagger.json"
EXCEL_PATH = "testcases/test_cases.xlsx"
MYSQL_CONFIG = {
"host": "localhost",
"user": "test",
"password": "test123",
"database": "api_test"
}
BASE_URL = "http://api.example.com"
```
该框架可通过以下命令启动测试:
```bash
python main.py --env=prod --report=html
```
后续可扩展功能:
- 支持多种数据源(CSV/YAML)
- 集成Allure测试报告
- 增加性能测试模块
- 实现CI/CD流水线集成
- 添加Mock Server支持
- 增加自动生成基础测试用例功能
建议采用分层设计模式,保持各模块的独立性,便于后续扩展和维护。