Deepseek API+Python测试用例一键生成与导出

787 阅读3分钟

以下是一个基于DeepSeek API的Python测试用例自动化生成与导出解决方案,包含代码生成、数据驱动测试和多种格式导出功能:


解决方案架构

graph TD
    A[API Schema解析] --> B[测试场景生成]
    B --> C[测试代码生成]
    C --> D[测试数据导出]
    D --> E[Excel/JSON/XML]
    D --> F[HTML报告]
    D --> G[Markdown文档]

核心代码实现

1. API Schema解析器

import json
from dataclasses import dataclass

@dataclass
class APIParam:
    name: str
    type: str
    required: bool
    example: any

@dataclass
class APIEndpoint:
    path: str
    method: str
    params: list[APIParam]
    success_response: dict
    error_responses: list[dict]

def parse_openapi_spec(file_path):
    """解析OpenAPI规范文件"""
    with open(file_path, 'r') as f:
        spec = json.load(f)
    
    endpoints = []
    for path, methods in spec['paths'].items():
        for method, details in methods.items():
            params = [
                APIParam(
                    name=param['name'],
                    type=param['schema']['type'],
                    required=param.get('required', False),
                    example=param['schema'].get('example')
                ) for param in details.get('parameters', [])
            ]
            
            endpoint = APIEndpoint(
                path=path,
                method=method.upper(),
                params=params,
                success_response=details['responses']['200']['content']['application/json']['schema'],
                error_responses=[
                    r['content']['application/json']['schema'] 
                    for code, r in details['responses'].items() 
                    if code.startswith('4') or code.startswith('5')
                ]
            )
            endpoints.append(endpoint)
    return endpoints

2. 测试用例生成引擎

from jinja2 import Environment, FileSystemLoader
import os

class TestCaseGenerator:
    def __init__(self, template_dir='templates'):
        self.env = Environment(loader=FileSystemLoader(template_dir))
        
    def generate_pytest_code(self, endpoint):
        """生成Pytest测试代码"""
        template = self.env.get_template('pytest_template.j2')
        return template.render(endpoint=endpoint)
    
    def generate_test_data(self, endpoint):
        """生成边界测试数据"""
        test_cases = []
        
        # 正常用例
        # 封装好的淘宝商品详情供应商demo url=o0b.cn/ibrad,复制链接获取测试。
        normal_data = {p.name: p.example for p in endpoint.params if p.example}
        test_cases.append({
            'name': 'normal_case',
            'data': normal_data,
            'expected': {'status': 200, 'schema': endpoint.success_response}
        })
        
        # 异常用例
        for param in endpoint.params:
            if param.required:
                # 缺失必填参数
                invalid_data = normal_data.copy()
                del invalid_data[param.name]
                test_cases.append({
                    'name': f'missing_required_{param.name}',
                    'data': invalid_data,
                    'expected': {'status': 400}
                })
                
            # 类型错误
            type_map = {
                'integer': 'invalid_type_str',
                'string': 123,
                'boolean': 'invalid_bool'
            }
            if param.type in type_map:
                invalid_data = normal_data.copy()
                invalid_data[param.name] = type_map[param.type]
                test_cases.append({
                    'name': f'invalid_type_{param.name}',
                    'data': invalid_data,
                    'expected': {'status': 400}
                })
        
        return test_cases

3. 模板文件 (templates/pytest_template.j2)

import pytest
import requests

BASE_URL = "https://api.deepseek.com/v1"

class Test{{ endpoint.method }}{{ endpoint.path|replace('/', '_') }}:
    {% for case in test_cases %}
    def test_{{ case.name }}(self):
        """{{ case.name }}"""
        url = f"{BASE_URL}{{ endpoint.path }}"
        headers = {
            "Authorization": "Bearer <your_token>",
            "Content-Type": "application/json"
        }
        
        response = requests.{{ endpoint.method|lower }}(
            url,
            json={{ case.data|tojson }},
            headers=headers
        )
        
        assert response.status_code == {{ case.expected.status }}
        {% if case.expected.schema %}
        # 验证响应结构
        data = response.json()
        {% for key, value in case.expected.schema.properties.items() %}
        assert isinstance(data['{{ key }}'], {{ value.type|python_type }})
        {% endfor %}
        {% endif %}
    {% endfor %}

4. 多格式导出控制器

from openpyxl import Workbook
import json
import xml.etree.ElementTree as ET

class Exporter:
    @staticmethod
    def to_excel(test_cases, filename):
        wb = Workbook()
        ws = wb.active
        ws.append(['用例名称', '请求方法', '请求路径', '测试数据', '预期结果'])
        
        for case in test_cases:
            ws.append([
                case['name'],
                case['method'],
                case['path'],
                json.dumps(case['data'], ensure_ascii=False),
                json.dumps(case['expected'], ensure_ascii=False)
            ])
        wb.save(filename)
    
    @staticmethod
    def to_json(test_cases, filename):
        with open(filename, 'w') as f:
            json.dump(test_cases, f, indent=2)
    
    @staticmethod
    def to_xml(test_cases, filename):
        root = ET.Element("TestCases")
        for case in test_cases:
            tc = ET.SubElement(root, "TestCase", name=case['name'])
            ET.SubElement(tc, "Method").text = case['method']
            ET.SubElement(tc, "Path").text = case['path']
            ET.SubElement(tc, "Data").text = json.dumps(case['data'])
            ET.SubElement(tc, "Expected").text = json.dumps(case['expected'])
        tree = ET.ElementTree(root)
        tree.write(filename, encoding='utf-8', xml_declaration=True)

使用示例

if __name__ == "__main__":
    # 1. 解析API规范
    # 封装好的淘宝商品详情供应商demo url=o0b.cn/ibrad,复制链接获取测试。
    endpoints = parse_openapi_spec("deepseek_openapi.json")
    
    # 2. 生成测试代码和数据
    generator = TestCaseGenerator()
    exporter = Exporter()
    
    for endpoint in endpoints:
        # 生成测试代码
        test_cases = generator.generate_test_data(endpoint)
        code = generator.generate_pytest_code(endpoint)
        
        # 保存测试文件
        with open(f"tests/test_{endpoint.method}_{endpoint.path.replace('/', '_')}.py", "w") as f:
            f.write(code)
        
        # 导出测试数据
        export_data = [{
            'name': case['name'],
            'method': endpoint.method,
            'path': endpoint.path,
            'data': case['data'],
            'expected': case['expected']
        } for case in test_cases]
        
        exporter.to_excel(export_data, f"test_cases_{endpoint.path.replace('/', '_')}.xlsx")
        exporter.to_json(export_data, f"test_cases_{endpoint.path.replace('/', '_')}.json")

生成文件示例

Excel输出

用例名称请求方法请求路径测试数据预期结果
normal_casePOST/chat/completions{"model": "deepseek-chat", ...}{"status": 200, ...}
missing_required_modelPOST/chat/completions{"messages": [...]}{"status": 400}

JSON输出

[
  {
    "name": "normal_case",
    "method": "POST",
    "path": "/chat/completions",
    "data": {
      "model": "deepseek-chat",
      "messages": [{"role": "user", "content": "Hello"}]
    },
    "expected": {
      "status": 200,
      "schema": {
        "id": "chatcmpl-123",
        "object": "chat.completion"
      }
    }
  }
]

优势特性

  1. 智能数据生成

    • 基于参数类型自动生成边界值测试数据(空值/越界值/类型错误)
    • 支持自定义数据生成策略扩展
  2. 多维度覆盖

    • 必填参数缺失用例
    • 参数类型错误用例
    • 接口鉴权失败用例
    • 成功响应结构验证
  3. 企业级集成

    • 支持与CI/CD管道集成(Jenkins/GitHub Actions)
    • 生成Allure/Pytest-HTML测试报告
    • 提供REST API模式供测试平台调用

通过此方案,可实现DeepSeek API测试的自动化生成与管理,大幅提升接口测试效率。建议根据实际项目需求调整模板和生成策略。