#!/usr/bin/env python # -*- coding: utf-8 -*- """ API测试工具 此工具使用DDMS测试编排器从YAPI或Swagger定义执行API测试。 支持使用规则库进行高级验证。 """ import os import sys import json import logging import argparse from pathlib import Path from ddms_compliance_suite.test_orchestrator import APITestOrchestrator, TestSummary # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) def parse_args(): """解析命令行参数""" parser = argparse.ArgumentParser(description='DDMS API测试工具') # 基本参数 parser.add_argument('--base-url', required=True, help='API基础URL') parser.add_argument('--verbose', '-v', action='store_true', help='启用详细日志') parser.add_argument('--output', '-o', help='输出文件路径') parser.add_argument('--format', choices=['json', 'html'], default='json', help='输出格式') # API定义参数 api_group = parser.add_argument_group('API定义源') api_group.add_argument('--yapi', help='YAPI定义文件路径') api_group.add_argument('--swagger', help='Swagger定义文件路径') # 过滤参数 filter_group = parser.add_argument_group('过滤选项') filter_group.add_argument('--categories', help='YAPI分类,逗号分隔') filter_group.add_argument('--tags', help='Swagger标签,逗号分隔') filter_group.add_argument('--list-categories', action='store_true', help='列出YAPI分类') filter_group.add_argument('--list-tags', action='store_true', help='列出Swagger标签') # 新增:自定义测试用例参数组 custom_tc_group = parser.add_argument_group('自定义测试用例选项') custom_tc_group.add_argument('--custom-test-cases-dir', default=None, # 或者 './custom_testcases' 如果想设为默认 help='存放自定义APITestCase Python文件的目录路径。如果未提供,则不加载自定义测试。') # 新增:LLM 配置选项 llm_group = parser.add_argument_group('LLM 配置选项 (可选)') llm_group.add_argument('--llm-api-key', default=os.environ.get("OPENAI_API_KEY"), # 尝试从环境变量获取 help='LLM服务的API密钥 (例如 OpenAI API Key)。默认从环境变量 OPENAI_API_KEY 读取。') llm_group.add_argument('--llm-base-url', default="https://dashscope.aliyuncs.com/compatible-mode/v1", help='LLM服务的自定义基础URL (例如 OpenAI API代理)。') llm_group.add_argument('--llm-model-name', default="qwen-plus", # 设置一个常用的默认模型 help='要使用的LLM模型名称 (例如 "gpt-3.5-turbo", "gpt-4")。') llm_group.add_argument('--use-llm-for-request-body', action='store_true', default=False, # 默认不使用LLM生成请求体 help='是否启用LLM为API请求生成请求体数据。') llm_group.add_argument('--use-llm-for-path-params', action='store_true', default=False, help='是否启用LLM为API请求生成路径参数。') llm_group.add_argument('--use-llm-for-query-params', action='store_true', default=False, help='是否启用LLM为API请求生成查询参数。') llm_group.add_argument('--use-llm-for-headers', action='store_true', default=False, help='是否启用LLM为API请求生成头部参数。') return parser.parse_args() def list_yapi_categories(yapi_file: str): """列出YAPI分类""" from ddms_compliance_suite.input_parser.parser import InputParser logger.info(f"从YAPI文件解析分类: {yapi_file}") parser = InputParser() parsed_yapi = parser.parse_yapi_spec(yapi_file) if not parsed_yapi: logger.error(f"解析YAPI文件失败: {yapi_file}") return print("\nYAPI分类:") for i, category in enumerate(parsed_yapi.categories, 1): print(f"{i}. {category.get('name', '未命名')} - {category.get('desc', '无描述')}") def list_swagger_tags(swagger_file: str): """列出Swagger标签""" from ddms_compliance_suite.input_parser.parser import InputParser logger.info(f"从Swagger文件解析标签: {swagger_file}") parser = InputParser() parsed_swagger = parser.parse_swagger_spec(swagger_file) if not parsed_swagger: logger.error(f"解析Swagger文件失败: {swagger_file}") return print("\nSwagger标签:") for i, tag in enumerate(parsed_swagger.tags, 1): print(f"{i}. {tag.get('name', '未命名')} - {tag.get('description', '无描述')}") def save_results(summary: TestSummary, output_file: str, format_type: str): """保存测试结果""" if format_type == 'json': with open(output_file, 'w', encoding='utf-8') as f: f.write(summary.to_json(pretty=True)) logger.info(f"测试结果已保存为JSON: {output_file}") elif format_type == 'html': # 创建简单的HTML报告 html_content = f"""
总测试数: {summary.total}
通过: {summary.passed}
失败: {summary.failed}
错误: {summary.error}
跳过: {summary.skipped}
成功率: {summary.success_rate:.2f}%
总耗时: {summary.duration:.2f}秒
开始时间: {summary.start_time.isoformat()}
结束时间: {summary.end_time.isoformat() if summary.end_time else 'N/A'}
| 端点 | 状态 | 消息 | 响应码 | 耗时(秒) |
|---|---|---|---|---|
| {result.endpoint_id} | {result.status} | {result.message} | {response_code} | {result.elapsed_time:.4f} |