zhouhui.jiang

update API测试

1 { 1 {
2 - "token": "eyJhbGciOiJIUzUxMiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwic3ViIjoiYWRtaW4iLCJpYXQiOjE3NjAzMjYxMTksImV4cCI6MTc2MDQxMjUxOX0.QiJRc8xCQN_MBEwH3BRK5fUW17pz_9s7fCvFJK1AIbqg8uqhezw-FVxUi7G5-gIf4zlJrovZpMB0VGg7xT3XDg", 2 + "token": "eyJhbGciOiJIUzUxMiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwic3ViIjoiYWRtaW4iLCJpYXQiOjE3NjAzMjY2OTIsImV4cCI6MTc2MDQxMzA5Mn0.g_bbqdvMIIoPws2bOC8AJpFHYo-zSFgybXAEJUF3rvheltchQG1q_jZZSSw2tWLQvZOjzFeJxOROJwKbu5JnIQ",
3 - "saved_at": 1760326119 3 + "saved_at": 1760326692
4 } 4 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -7,6 +7,203 @@ Python 3.7.8 兼容 ...@@ -7,6 +7,203 @@ Python 3.7.8 兼容
7 7
8 import os 8 import os
9 import sys 9 import sys
10 +import json
11 +import time
12 +from datetime import datetime
13 +from typing import Dict, List, Any
14 +
15 +class TestReporter:
16 + """测试报告生成器"""
17 +
18 + def __init__(self):
19 + self.test_results = []
20 + self.start_time = None
21 + self.end_time = None
22 +
23 + def start_test_suite(self):
24 + """开始测试套件"""
25 + self.start_time = datetime.now()
26 +
27 + def end_test_suite(self):
28 + """结束测试套件"""
29 + self.end_time = datetime.now()
30 +
31 + def add_test_result(self, test_name: str, script_name: str, success: bool,
32 + execution_time: float, error_message: str = None,
33 + output: str = None):
34 + """添加测试结果"""
35 + result = {
36 + 'test_name': test_name,
37 + 'script_name': script_name,
38 + 'success': success,
39 + 'execution_time': execution_time,
40 + 'error_message': error_message,
41 + 'output': output,
42 + 'timestamp': datetime.now().isoformat()
43 + }
44 + self.test_results.append(result)
45 +
46 + def generate_html_report(self, output_file: str = None):
47 + """生成HTML格式的测试报告"""
48 + if output_file is None:
49 + # 确保reports目录存在
50 + reports_dir = "reports"
51 + if not os.path.exists(reports_dir):
52 + os.makedirs(reports_dir)
53 + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
54 + output_file = os.path.join(reports_dir, f"test_report_{timestamp}.html")
55 +
56 + total_tests = len(self.test_results)
57 + passed_tests = sum(1 for r in self.test_results if r['success'])
58 + failed_tests = total_tests - passed_tests
59 + success_rate = (passed_tests / total_tests * 100) if total_tests > 0 else 0
60 +
61 + total_time = (self.end_time - self.start_time).total_seconds() if self.end_time and self.start_time else 0
62 +
63 + html_content = f"""
64 +<!DOCTYPE html>
65 +<html lang="zh-CN">
66 +<head>
67 + <meta charset="UTF-8">
68 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
69 + <title>Apple ERP API 测试报告</title>
70 + <style>
71 + body {{ font-family: 'Microsoft YaHei', Arial, sans-serif; margin: 20px; background-color: #f5f5f5; }}
72 + .container {{ max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }}
73 + .header {{ text-align: center; margin-bottom: 30px; }}
74 + .header h1 {{ color: #333; margin-bottom: 10px; }}
75 + .header .timestamp {{ color: #666; font-size: 14px; }}
76 + .summary {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }}
77 + .summary-card {{ background: #f8f9fa; padding: 20px; border-radius: 6px; text-align: center; border-left: 4px solid #007bff; }}
78 + .summary-card.success {{ border-left-color: #28a745; }}
79 + .summary-card.failure {{ border-left-color: #dc3545; }}
80 + .summary-card h3 {{ margin: 0 0 10px 0; color: #333; }}
81 + .summary-card .number {{ font-size: 2em; font-weight: bold; color: #007bff; }}
82 + .summary-card.success .number {{ color: #28a745; }}
83 + .summary-card.failure .number {{ color: #dc3545; }}
84 + .test-results {{ margin-top: 30px; }}
85 + .test-item {{ margin-bottom: 20px; padding: 15px; border-radius: 6px; border: 1px solid #ddd; }}
86 + .test-item.success {{ background: #d4edda; border-color: #c3e6cb; }}
87 + .test-item.failure {{ background: #f8d7da; border-color: #f5c6cb; }}
88 + .test-header {{ display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }}
89 + .test-name {{ font-weight: bold; font-size: 16px; }}
90 + .test-status {{ padding: 4px 8px; border-radius: 4px; font-size: 12px; font-weight: bold; }}
91 + .test-status.success {{ background: #28a745; color: white; }}
92 + .test-status.failure {{ background: #dc3545; color: white; }}
93 + .test-details {{ font-size: 14px; color: #666; }}
94 + .test-output {{ background: #f8f9fa; padding: 10px; border-radius: 4px; margin-top: 10px; font-family: monospace; font-size: 12px; max-height: 200px; overflow-y: auto; }}
95 + .error-message {{ color: #dc3545; font-weight: bold; }}
96 + </style>
97 +</head>
98 +<body>
99 + <div class="container">
100 + <div class="header">
101 + <h1>🍎 Apple ERP API 测试报告</h1>
102 + <div class="timestamp">生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</div>
103 + </div>
104 +
105 + <div class="summary">
106 + <div class="summary-card">
107 + <h3>总测试数</h3>
108 + <div class="number">{total_tests}</div>
109 + </div>
110 + <div class="summary-card success">
111 + <h3>通过测试</h3>
112 + <div class="number">{passed_tests}</div>
113 + </div>
114 + <div class="summary-card failure">
115 + <h3>失败测试</h3>
116 + <div class="number">{failed_tests}</div>
117 + </div>
118 + <div class="summary-card">
119 + <h3>成功率</h3>
120 + <div class="number">{success_rate:.1f}%</div>
121 + </div>
122 + <div class="summary-card">
123 + <h3>执行时间</h3>
124 + <div class="number">{total_time:.2f}s</div>
125 + </div>
126 + </div>
127 +
128 + <div class="test-results">
129 + <h2>详细测试结果</h2>
130 +"""
131 +
132 + for result in self.test_results:
133 + status_class = "success" if result['success'] else "failure"
134 + status_text = "✅ 通过" if result['success'] else "❌ 失败"
135 +
136 + html_content += f"""
137 + <div class="test-item {status_class}">
138 + <div class="test-header">
139 + <div class="test-name">{result['test_name']}</div>
140 + <div class="test-status {status_class}">{status_text}</div>
141 + </div>
142 + <div class="test-details">
143 + <strong>脚本:</strong> {result['script_name']}<br>
144 + <strong>执行时间:</strong> {result['execution_time']:.2f}秒<br>
145 + <strong>时间戳:</strong> {result['timestamp']}
146 +"""
147 +
148 + if result['error_message']:
149 + html_content += f'<div class="error-message">错误信息: {result["error_message"]}</div>'
150 +
151 + if result['output']:
152 + html_content += f'<div class="test-output">{result["output"]}</div>'
153 +
154 + html_content += """
155 + </div>
156 + </div>
157 +"""
158 +
159 + html_content += """
160 + </div>
161 + </div>
162 +</body>
163 +</html>
164 +"""
165 +
166 + with open(output_file, 'w', encoding='utf-8') as f:
167 + f.write(html_content)
168 +
169 + return output_file
170 +
171 + def generate_json_report(self, output_file: str = None):
172 + """生成JSON格式的测试报告"""
173 + if output_file is None:
174 + # 确保reports目录存在
175 + reports_dir = "reports"
176 + if not os.path.exists(reports_dir):
177 + os.makedirs(reports_dir)
178 + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
179 + output_file = os.path.join(reports_dir, f"test_report_{timestamp}.json")
180 +
181 + total_tests = len(self.test_results)
182 + passed_tests = sum(1 for r in self.test_results if r['success'])
183 + failed_tests = total_tests - passed_tests
184 + success_rate = (passed_tests / total_tests * 100) if total_tests > 0 else 0
185 +
186 + total_time = (self.end_time - self.start_time).total_seconds() if self.end_time and self.start_time else 0
187 +
188 + report_data = {
189 + 'test_suite': 'Apple ERP API Tests',
190 + 'generated_at': datetime.now().isoformat(),
191 + 'summary': {
192 + 'total_tests': total_tests,
193 + 'passed_tests': passed_tests,
194 + 'failed_tests': failed_tests,
195 + 'success_rate': success_rate,
196 + 'total_execution_time': total_time,
197 + 'start_time': self.start_time.isoformat() if self.start_time else None,
198 + 'end_time': self.end_time.isoformat() if self.end_time else None
199 + },
200 + 'test_results': self.test_results
201 + }
202 +
203 + with open(output_file, 'w', encoding='utf-8') as f:
204 + json.dump(report_data, f, ensure_ascii=False, indent=2)
205 +
206 + return output_file
10 207
11 def main(): 208 def main():
12 """主函数:按顺序运行所有测试""" 209 """主函数:按顺序运行所有测试"""
...@@ -14,6 +211,10 @@ def main(): ...@@ -14,6 +211,10 @@ def main():
14 print("Apple ERP API 测试套件") 211 print("Apple ERP API 测试套件")
15 print("=" * 60) 212 print("=" * 60)
16 213
214 + # 初始化测试报告器
215 + reporter = TestReporter()
216 + reporter.start_test_suite()
217 +
17 # 测试脚本列表(按执行顺序) 218 # 测试脚本列表(按执行顺序)
18 tests = [ 219 tests = [
19 ("认证登录测试", "test_auth.py"), 220 ("认证登录测试", "test_auth.py"),
...@@ -31,8 +232,15 @@ def main(): ...@@ -31,8 +232,15 @@ def main():
31 232
32 if not os.path.exists(script_name): 233 if not os.path.exists(script_name):
33 print(f"❌ 脚本不存在: {script_name}") 234 print(f"❌ 脚本不存在: {script_name}")
235 + reporter.add_test_result(test_name, script_name, False, 0,
236 + f"脚本不存在: {script_name}")
34 continue 237 continue
35 238
239 + start_time = time.time()
240 + test_output = []
241 + error_message = None
242 + test_success = False
243 +
36 try: 244 try:
37 # 直接导入并运行测试函数 245 # 直接导入并运行测试函数
38 module_name = script_name.replace('.py', '') 246 module_name = script_name.replace('.py', '')
...@@ -42,36 +250,64 @@ def main(): ...@@ -42,36 +250,64 @@ def main():
42 if success: 250 if success:
43 print(f"✅ {test_name} 执行成功") 251 print(f"✅ {test_name} 执行成功")
44 success_count += 1 252 success_count += 1
253 + test_success = True
45 else: 254 else:
46 print(f"❌ {test_name} 执行失败") 255 print(f"❌ {test_name} 执行失败")
256 + error_message = "登录失败"
47 elif module_name == 'test_users': 257 elif module_name == 'test_users':
48 from test_users import run_user_tests 258 from test_users import run_user_tests
49 run_user_tests() 259 run_user_tests()
50 print(f"✅ {test_name} 执行成功") 260 print(f"✅ {test_name} 执行成功")
51 success_count += 1 261 success_count += 1
262 + test_success = True
52 elif module_name == 'test_roles': 263 elif module_name == 'test_roles':
53 from test_roles import run_role_tests 264 from test_roles import run_role_tests
54 run_role_tests() 265 run_role_tests()
55 print(f"✅ {test_name} 执行成功") 266 print(f"✅ {test_name} 执行成功")
56 success_count += 1 267 success_count += 1
268 + test_success = True
57 elif module_name == 'test_menus': 269 elif module_name == 'test_menus':
58 from test_menus import run_menu_tests 270 from test_menus import run_menu_tests
59 run_menu_tests() 271 run_menu_tests()
60 print(f"✅ {test_name} 执行成功") 272 print(f"✅ {test_name} 执行成功")
61 success_count += 1 273 success_count += 1
274 + test_success = True
62 elif module_name == 'test_dicts': 275 elif module_name == 'test_dicts':
63 from test_dicts import run_dict_tests 276 from test_dicts import run_dict_tests
64 run_dict_tests() 277 run_dict_tests()
65 print(f"✅ {test_name} 执行成功") 278 print(f"✅ {test_name} 执行成功")
66 success_count += 1 279 success_count += 1
280 + test_success = True
281 +
67 except Exception as e: 282 except Exception as e:
68 print(f"❌ {test_name} 执行失败: {e}") 283 print(f"❌ {test_name} 执行失败: {e}")
284 + error_message = str(e)
285 +
286 + execution_time = time.time() - start_time
287 + reporter.add_test_result(test_name, script_name, test_success,
288 + execution_time, error_message,
289 + '\n'.join(test_output) if test_output else None)
290 +
291 + # 结束测试套件
292 + reporter.end_test_suite()
69 293
70 # 总结 294 # 总结
71 print("\n" + "=" * 60) 295 print("\n" + "=" * 60)
72 print(f"测试完成: {success_count}/{total_count} 个测试通过") 296 print(f"测试完成: {success_count}/{total_count} 个测试通过")
73 print("=" * 60) 297 print("=" * 60)
74 298
299 + # 生成测试报告
300 + try:
301 + html_report = reporter.generate_html_report()
302 + json_report = reporter.generate_json_report()
303 +
304 + print(f"\n📊 测试报告已生成:")
305 + print(f" HTML报告: {html_report}")
306 + print(f" JSON报告: {json_report}")
307 +
308 + except Exception as e:
309 + print(f"⚠️ 生成测试报告时出错: {e}")
310 +
75 if success_count == total_count: 311 if success_count == total_count:
76 print("🎉 所有测试都通过了!") 312 print("🎉 所有测试都通过了!")
77 return 0 313 return 0
......