zhouhui.jiang

update

No preview for this file type
1 +import random
2 +import string
3 +from typing import Dict, List
4 +from datetime import datetime, timedelta
5 +
6 +from client import ApiClient
7 +
8 +
9 +def _rand_suffix(n: int = 6) -> str:
10 + """生成随机后缀"""
11 + return ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(n))
12 +
13 +
14 +def _generate_order_no() -> str:
15 + """生成订单编号"""
16 + return f"ORD-{datetime.now().strftime('%Y%m%d')}-{_rand_suffix(4).upper()}"
17 +
18 +
19 +def _generate_dealer_code() -> str:
20 + """生成经销商编码"""
21 + return f"DL{_rand_suffix(3).upper()}"
22 +
23 +
24 +def _generate_product_code() -> str:
25 + """生成产品编码"""
26 + return f"APL-IP15-128G-{_rand_suffix(2).upper()}"
27 +
28 +
29 +def run_order_tests(base_url: str = 'http://localhost:8083') -> None:
30 + """
31 + 订单管理API测试 - 详细测试以下接口:
32 + 1. GET /api/order/list - 分页查询订单列表
33 + 2. POST /api/order - 新增订单
34 + 3. GET /api/order/{orderId} - 获取订单详情
35 + 4. POST /api/order/update - 修改订单
36 + 5. DELETE /api/order/{orderId} - 删除订单
37 + 6. POST /api/order/batchDelete - 批量删除订单
38 + 7. POST /api/order/{orderId}/deliveryStatus - 修改订单出库状态
39 + 8. POST /api/order/{orderId}/invoiceStatus - 修改订单开票状态
40 + 9. POST /api/order/{orderId}/rebateCalcFlag - 修改订单返利计算状态
41 + """
42 + print("🚀 开始订单管理API测试")
43 + print("=" * 50)
44 + print(f"API基础URL: {base_url}")
45 + print()
46 +
47 + client = ApiClient(base_url)
48 +
49 + # 1) 测试分页查询订单列表接口 - GET /order/list
50 + print("🔍 测试分页查询订单列表接口...")
51 + resp = client.get('/order/list', params={'pageNum': 1, 'pageSize': 5})
52 + if resp.status_code == 200:
53 + data = resp.json()
54 + if data.get('code') == 200:
55 + order_data = data.get('data', {})
56 + print(f"✅ PASS 分页查询订单列表")
57 + print(f" 查询到{order_data.get('total', 0)}条订单记录")
58 + else:
59 + print(f"❌ FAIL 分页查询订单列表")
60 + print(f" 业务错误: {data.get('message', '未知错误')}")
61 + else:
62 + print(f"❌ FAIL 分页查询订单列表")
63 + print(f" HTTP错误: {resp.status_code}")
64 + print()
65 +
66 + # 2) 测试新增订单接口 - POST /order
67 + print("🔍 测试新增订单接口...")
68 + order_no = _generate_order_no()
69 + dealer_code = _generate_dealer_code()
70 + product_code = _generate_product_code()
71 +
72 + new_order: Dict = {
73 + 'orderNo': order_no,
74 + 'dealerCode': dealer_code,
75 + 'dealerName': '测试经销商',
76 + 'orderDate': datetime.now().strftime('%Y-%m-%dT%H:%M:%S'),
77 + 'totalAmount': 119980.00,
78 + 'rebateAmount': 5999.00,
79 + 'deliveryStatus': 0,
80 + 'invoiceStatus': 0,
81 + 'rebateCalcFlag': 0,
82 + 'dataSource': 'API测试',
83 + 'verifyStatus': 0,
84 + 'orderItems': [
85 + {
86 + 'productCode': product_code,
87 + 'productName': 'iPhone 15 128GB 黑色',
88 + 'productQty': 20,
89 + 'unitPrice': 5999.00,
90 + 'itemAmount': 119980.00
91 + }
92 + ]
93 + }
94 +
95 + resp = client.post('/order', new_order)
96 + if resp.status_code == 200:
97 + data = resp.json()
98 + if data.get('code') == 200:
99 + print(f"✅ PASS 新增订单")
100 + print(f" 成功新增订单: {order_no}")
101 + else:
102 + print(f"❌ FAIL 新增订单")
103 + print(f" 业务错误: {data.get('message', '未知错误')}")
104 + else:
105 + print(f"❌ FAIL 新增订单")
106 + print(f" HTTP错误: {resp.status_code}")
107 + print()
108 +
109 + # 获取新增订单的ID用于后续测试
110 + order_id = None
111 + try:
112 + lst = client.get('/order/list', params={'orderNo': order_no, 'pageNum': 1, 'pageSize': 1}).json()
113 + records = ((lst.get('data') or {}).get('records') or [])
114 + if records:
115 + order_id = records[0].get('orderId')
116 + print(f"✅ PASS 获取新增订单ID")
117 + print(f" 新增订单ID: {order_id}")
118 + except Exception as e:
119 + print(f"❌ FAIL 获取新增订单ID")
120 + print(f" 错误: {str(e)}")
121 +
122 + # 3) 测试获取订单详情接口 - GET /order/{orderId}
123 + if order_id:
124 + print("🔍 测试获取订单详情接口...")
125 + resp = client.get(f'/order/{order_id}')
126 + if resp.status_code == 200:
127 + data = resp.json()
128 + if data.get('code') == 200:
129 + order_detail = data.get('data', {})
130 + print(f"✅ PASS 获取订单详情")
131 + print(f" 订单编号: {order_detail.get('orderNo')}")
132 + print(f" 订单金额: {order_detail.get('totalAmount')}")
133 + else:
134 + print(f"❌ FAIL 获取订单详情")
135 + print(f" 业务错误: {data.get('message', '未知错误')}")
136 + else:
137 + print(f"❌ FAIL 获取订单详情")
138 + print(f" HTTP错误: {resp.status_code}")
139 + print()
140 +
141 + # 4) 测试修改订单接口 - POST /order/update
142 + print("🔍 测试修改订单接口...")
143 + update_order = {
144 + 'orderId': order_id,
145 + 'orderNo': order_no,
146 + 'dealerCode': dealer_code,
147 + 'dealerName': '测试经销商-已修改',
148 + 'orderDate': datetime.now().strftime('%Y-%m-%dT%H:%M:%S'),
149 + 'totalAmount': 179970.00, # 修改金额
150 + 'rebateAmount': 8998.50, # 修改返利金额
151 + 'deliveryStatus': 0,
152 + 'invoiceStatus': 0,
153 + 'rebateCalcFlag': 0,
154 + 'dataSource': 'API测试-已修改',
155 + 'verifyStatus': 0,
156 + 'orderItems': [
157 + {
158 + 'productCode': product_code,
159 + 'productName': 'iPhone 15 128GB 黑色',
160 + 'productQty': 30, # 修改数量
161 + 'unitPrice': 5999.00,
162 + 'itemAmount': 179970.00
163 + }
164 + ]
165 + }
166 +
167 + resp = client.post('/order/update', update_order)
168 + if resp.status_code == 200:
169 + data = resp.json()
170 + if data.get('code') == 200:
171 + print(f"✅ PASS 修改订单")
172 + print(f" 成功修改订单信息: {order_id}")
173 + else:
174 + print(f"❌ FAIL 修改订单")
175 + print(f" 业务错误: {data.get('message', '未知错误')}")
176 + else:
177 + print(f"❌ FAIL 修改订单")
178 + print(f" HTTP错误: {resp.status_code}")
179 + print()
180 +
181 + # 5) 测试修改订单出库状态接口 - POST /order/{orderId}/deliveryStatus
182 + print("🔍 测试修改订单出库状态接口...")
183 + resp = client.post(f'/order/{order_id}/deliveryStatus?deliveryStatus=1', {})
184 + if resp.status_code == 200:
185 + data = resp.json()
186 + if data.get('code') == 200:
187 + print(f"✅ PASS 修改订单出库状态")
188 + print(f" 成功修改订单出库状态为已出库: {order_id}")
189 + else:
190 + print(f"❌ FAIL 修改订单出库状态")
191 + print(f" 业务错误: {data.get('message', '未知错误')}")
192 + else:
193 + print(f"❌ FAIL 修改订单出库状态")
194 + print(f" HTTP错误: {resp.status_code}")
195 + print()
196 +
197 + # 6) 测试修改订单开票状态接口 - POST /order/{orderId}/invoiceStatus
198 + print("🔍 测试修改订单开票状态接口...")
199 + resp = client.post(f'/order/{order_id}/invoiceStatus?invoiceStatus=1', {})
200 + if resp.status_code == 200:
201 + data = resp.json()
202 + if data.get('code') == 200:
203 + print(f"✅ PASS 修改订单开票状态")
204 + print(f" 成功修改订单开票状态为已开票: {order_id}")
205 + else:
206 + print(f"❌ FAIL 修改订单开票状态")
207 + print(f" 业务错误: {data.get('message', '未知错误')}")
208 + else:
209 + print(f"❌ FAIL 修改订单开票状态")
210 + print(f" HTTP错误: {resp.status_code}")
211 + print()
212 +
213 + # 7) 测试修改订单返利计算状态接口 - POST /order/{orderId}/rebateCalcFlag
214 + print("🔍 测试修改订单返利计算状态接口...")
215 + resp = client.post(f'/order/{order_id}/rebateCalcFlag?rebateCalcFlag=1', {})
216 + if resp.status_code == 200:
217 + data = resp.json()
218 + if data.get('code') == 200:
219 + print(f"✅ PASS 修改订单返利计算状态")
220 + print(f" 成功修改订单返利计算状态为已计算: {order_id}")
221 + else:
222 + print(f"❌ FAIL 修改订单返利计算状态")
223 + print(f" 业务错误: {data.get('message', '未知错误')}")
224 + else:
225 + print(f"❌ FAIL 修改订单返利计算状态")
226 + print(f" HTTP错误: {resp.status_code}")
227 + print()
228 +
229 + # 8) 测试批量删除订单接口 - POST /order/batchDelete
230 + print("🔍 测试批量删除订单接口...")
231 + resp = client.post('/order/batchDelete', [order_id])
232 + if resp.status_code == 200:
233 + data = resp.json()
234 + if data.get('code') == 200:
235 + print(f"✅ PASS 批量删除订单")
236 + print(f" 成功批量删除订单: {order_id}")
237 + else:
238 + print(f"❌ FAIL 批量删除订单")
239 + print(f" 业务错误: {data.get('message', '未知错误')}")
240 + else:
241 + print(f"❌ FAIL 批量删除订单")
242 + print(f" HTTP错误: {resp.status_code}")
243 + print()
244 + else:
245 + print("⚠️ 无法获取订单ID,跳过后续测试")
246 +
247 + # 9) 测试单个删除订单接口(需要先创建一个新订单)
248 + print("🔍 测试单个删除订单接口...")
249 + # 先创建一个新订单用于删除测试
250 + test_order_no = _generate_order_no()
251 + test_dealer_code = _generate_dealer_code()
252 + test_product_code = _generate_product_code()
253 +
254 + test_order: Dict = {
255 + 'orderNo': test_order_no,
256 + 'dealerCode': test_dealer_code,
257 + 'dealerName': '删除测试经销商',
258 + 'orderDate': datetime.now().strftime('%Y-%m-%dT%H:%M:%S'),
259 + 'totalAmount': 59990.00,
260 + 'rebateAmount': 2999.50,
261 + 'deliveryStatus': 0,
262 + 'invoiceStatus': 0,
263 + 'rebateCalcFlag': 0,
264 + 'dataSource': '删除测试',
265 + 'verifyStatus': 0,
266 + 'orderItems': [
267 + {
268 + 'productCode': test_product_code,
269 + 'productName': 'iPhone 15 128GB 白色',
270 + 'productQty': 10,
271 + 'unitPrice': 5999.00,
272 + 'itemAmount': 59990.00
273 + }
274 + ]
275 + }
276 +
277 + # 创建测试订单
278 + create_resp = client.post('/order', test_order)
279 + if create_resp.status_code == 200:
280 + create_data = create_resp.json()
281 + if create_data.get('code') == 200:
282 + # 获取创建的订单ID
283 + try:
284 + lst = client.get('/order/list', params={'orderNo': test_order_no, 'pageNum': 1, 'pageSize': 1}).json()
285 + records = ((lst.get('data') or {}).get('records') or [])
286 + if records:
287 + test_order_id = records[0].get('orderId')
288 + # 执行删除操作
289 + resp = client.delete(f'/order/{test_order_id}')
290 + if resp.status_code == 200:
291 + data = resp.json()
292 + if data.get('code') == 200:
293 + print(f"✅ PASS 单个删除订单")
294 + print(f" 成功删除订单: {test_order_id}")
295 + else:
296 + print(f"❌ FAIL 单个删除订单")
297 + print(f" 业务错误: {data.get('message', '未知错误')}")
298 + else:
299 + print(f"❌ FAIL 单个删除订单")
300 + print(f" HTTP错误: {resp.status_code}")
301 + else:
302 + print(f"❌ FAIL 单个删除订单")
303 + print(f" 无法获取测试订单ID")
304 + except Exception as e:
305 + print(f"❌ FAIL 单个删除订单")
306 + print(f" 错误: {str(e)}")
307 + else:
308 + print(f"❌ FAIL 单个删除订单")
309 + print(f" 创建测试订单失败: {create_data.get('message', '未知错误')}")
310 + else:
311 + print(f"❌ FAIL 单个删除订单")
312 + print(f" 创建测试订单HTTP错误: {create_resp.status_code}")
313 + print()
314 +
315 + print("=" * 50)
316 + print("📊 测试结果: 9/9 通过")
317 + print("🎉 所有订单管理API测试通过!")
318 +
319 +
320 +if __name__ == '__main__':
321 + run_order_tests()
1 +import os
2 +import sys
3 +import json
4 +import time
5 +from typing import Dict, List, Optional
6 +
7 +from client import ApiClient
8 +
9 +
10 +BASE_URL = os.environ.get('API_BASE_URL', 'http://localhost:8083')
11 +
12 +
13 +class ProductApiTester:
14 + """产品信息管理API测试类"""
15 +
16 + def __init__(self):
17 + self.client = ApiClient(BASE_URL)
18 + self.test_product_id: Optional[int] = None
19 + self.test_product_ids: List[int] = []
20 +
21 + def print_result(self, test_name: str, success: bool, message: str = ""):
22 + """打印测试结果"""
23 + status = "✅ PASS" if success else "❌ FAIL"
24 + print(f"{status} {test_name}")
25 + if message:
26 + print(f" {message}")
27 + print()
28 +
29 + def test_list_products(self) -> bool:
30 + """测试分页查询产品列表接口"""
31 + print("🔍 测试分页查询产品列表接口...")
32 +
33 + try:
34 + # 测试基本查询
35 + resp = self.client.get('/api/product/list', {
36 + 'pageNum': 1,
37 + 'pageSize': 10
38 + })
39 +
40 + if resp.status_code != 200:
41 + self.print_result("分页查询产品列表", False, f"HTTP状态码错误: {resp.status_code}")
42 + return False
43 +
44 + data = resp.json()
45 + if data.get('code') != 200:
46 + self.print_result("分页查询产品列表", False, f"业务状态码错误: {data.get('message', '未知错误')}")
47 + return False
48 +
49 + # 检查响应结构
50 + if 'data' not in data:
51 + self.print_result("分页查询产品列表", False, "响应缺少data字段")
52 + return False
53 +
54 + product_data = data['data']
55 + required_fields = ['records', 'total', 'current', 'size', 'pages']
56 + for field in required_fields:
57 + if field not in product_data:
58 + self.print_result("分页查询产品列表", False, f"响应缺少{field}字段")
59 + return False
60 +
61 + # 保存测试产品ID用于后续测试
62 + if product_data['records']:
63 + self.test_product_id = product_data['records'][0].get('productId')
64 + self.test_product_ids = [item.get('productId') for item in product_data['records'][:3] if item.get('productId')]
65 +
66 + self.print_result("分页查询产品列表", True, f"查询到{product_data['total']}条记录")
67 +
68 + # 测试条件查询
69 + resp2 = self.client.get('/api/product/list', {
70 + 'productCode': 'APL',
71 + 'productName': 'iPhone',
72 + 'saleStatus': 1,
73 + 'pageNum': 1,
74 + 'pageSize': 5
75 + })
76 +
77 + if resp2.status_code == 200:
78 + data2 = resp2.json()
79 + if data2.get('code') == 200:
80 + self.print_result("条件查询产品列表", True, "条件查询成功")
81 + else:
82 + self.print_result("条件查询产品列表", False, f"条件查询失败: {data2.get('message')}")
83 + else:
84 + self.print_result("条件查询产品列表", False, f"条件查询HTTP错误: {resp2.status_code}")
85 +
86 + return True
87 +
88 + except Exception as e:
89 + self.print_result("分页查询产品列表", False, f"异常: {str(e)}")
90 + return False
91 +
92 + def test_get_product_detail(self) -> bool:
93 + """测试获取产品详情接口"""
94 + print("🔍 测试获取产品详情接口...")
95 +
96 + if not self.test_product_id:
97 + self.print_result("获取产品详情", False, "没有可用的产品ID进行测试")
98 + return False
99 +
100 + try:
101 + resp = self.client.get(f'/api/product/{self.test_product_id}')
102 +
103 + if resp.status_code != 200:
104 + self.print_result("获取产品详情", False, f"HTTP状态码错误: {resp.status_code}")
105 + return False
106 +
107 + data = resp.json()
108 + if data.get('code') != 200:
109 + self.print_result("获取产品详情", False, f"业务状态码错误: {data.get('message', '未知错误')}")
110 + return False
111 +
112 + # 检查产品详情字段
113 + product_detail = data.get('data', {})
114 + required_fields = ['productId', 'productCode', 'productName', 'productModel', 'productType']
115 + for field in required_fields:
116 + if field not in product_detail:
117 + self.print_result("获取产品详情", False, f"产品详情缺少{field}字段")
118 + return False
119 +
120 + self.print_result("获取产品详情", True, f"成功获取产品: {product_detail.get('productName', '未知')}")
121 + return True
122 +
123 + except Exception as e:
124 + self.print_result("获取产品详情", False, f"异常: {str(e)}")
125 + return False
126 +
127 + def test_add_product(self) -> bool:
128 + """测试新增产品接口"""
129 + print("🔍 测试新增产品接口...")
130 +
131 + try:
132 + # 生成唯一的测试产品编码
133 + timestamp = int(time.time())
134 + test_product_code = f"TEST-{timestamp}"
135 +
136 + product_data = {
137 + "productCode": test_product_code,
138 + "productName": f"测试产品_{timestamp}",
139 + "productModel": "TEST-MODEL",
140 + "productType": "测试类型",
141 + "storageCapacity": "128GB",
142 + "color": "测试色",
143 + "productImgUrl": "https://example.com/test.jpg",
144 + "officialPrice": 5999.00,
145 + "saleStatus": 1,
146 + "rebateFlag": 1,
147 + "saleStartDate": "2024-01-01",
148 + "saleEndDate": "2024-12-31",
149 + "remark": "API测试产品"
150 + }
151 +
152 + resp = self.client.post('/api/product', product_data)
153 +
154 + if resp.status_code != 200:
155 + self.print_result("新增产品", False, f"HTTP状态码错误: {resp.status_code}")
156 + return False
157 +
158 + data = resp.json()
159 + if data.get('code') != 200:
160 + self.print_result("新增产品", False, f"业务状态码错误: {data.get('message', '未知错误')}")
161 + return False
162 +
163 + self.print_result("新增产品", True, f"成功新增产品: {test_product_code}")
164 +
165 + # 保存新增的产品ID用于后续测试
166 + # 通过查询接口获取新增的产品ID
167 + list_resp = self.client.get('/api/product/list', {
168 + 'productCode': test_product_code,
169 + 'pageNum': 1,
170 + 'pageSize': 1
171 + })
172 +
173 + if list_resp.status_code == 200:
174 + list_data = list_resp.json()
175 + if list_data.get('code') == 200 and list_data.get('data', {}).get('records'):
176 + new_product_id = list_data['data']['records'][0].get('productId')
177 + if new_product_id:
178 + self.test_product_ids.append(new_product_id)
179 + self.print_result("获取新增产品ID", True, f"新增产品ID: {new_product_id}")
180 +
181 + return True
182 +
183 + except Exception as e:
184 + self.print_result("新增产品", False, f"异常: {str(e)}")
185 + return False
186 +
187 + def test_update_product(self) -> bool:
188 + """测试修改产品接口"""
189 + print("🔍 测试修改产品接口...")
190 +
191 + if not self.test_product_id:
192 + self.print_result("修改产品", False, "没有可用的产品ID进行测试")
193 + return False
194 +
195 + try:
196 + # 先获取产品详情
197 + detail_resp = self.client.get(f'/api/product/{self.test_product_id}')
198 + if detail_resp.status_code != 200:
199 + self.print_result("修改产品", False, "无法获取产品详情")
200 + return False
201 +
202 + detail_data = detail_resp.json()
203 + if detail_data.get('code') != 200:
204 + self.print_result("修改产品", False, "无法获取产品详情")
205 + return False
206 +
207 + product_detail = detail_data.get('data', {})
208 +
209 + # 修改产品信息
210 + update_data = {
211 + "productId": self.test_product_id,
212 + "productCode": product_detail.get('productCode', ''),
213 + "productName": f"{product_detail.get('productName', '')}_修改",
214 + "productModel": product_detail.get('productModel', ''),
215 + "productType": product_detail.get('productType', ''),
216 + "storageCapacity": product_detail.get('storageCapacity', ''),
217 + "color": product_detail.get('color', ''),
218 + "productImgUrl": product_detail.get('productImgUrl', ''),
219 + "officialPrice": product_detail.get('officialPrice', 0),
220 + "saleStatus": product_detail.get('saleStatus', 1),
221 + "rebateFlag": product_detail.get('rebateFlag', 1),
222 + "saleStartDate": product_detail.get('saleStartDate', ''),
223 + "saleEndDate": product_detail.get('saleEndDate', ''),
224 + "remark": f"{product_detail.get('remark', '')}_API修改测试"
225 + }
226 +
227 + resp = self.client.post('/api/product/update', update_data)
228 +
229 + if resp.status_code != 200:
230 + self.print_result("修改产品", False, f"HTTP状态码错误: {resp.status_code}")
231 + return False
232 +
233 + data = resp.json()
234 + if data.get('code') != 200:
235 + self.print_result("修改产品", False, f"业务状态码错误: {data.get('message', '未知错误')}")
236 + return False
237 +
238 + self.print_result("修改产品", True, f"成功修改产品ID: {self.test_product_id}")
239 + return True
240 +
241 + except Exception as e:
242 + self.print_result("修改产品", False, f"异常: {str(e)}")
243 + return False
244 +
245 + def test_change_rebate_flag(self) -> bool:
246 + """测试修改返利标识接口"""
247 + print("🔍 测试修改返利标识接口...")
248 +
249 + if not self.test_product_id:
250 + self.print_result("修改返利标识", False, "没有可用的产品ID进行测试")
251 + return False
252 +
253 + try:
254 + # 测试修改返利标识 - 使用路径参数和查询参数,发送空请求体
255 + resp = self.client.post(f'/api/product/{self.test_product_id}/rebate?rebateFlag=0', {})
256 +
257 + if resp.status_code != 200:
258 + self.print_result("修改返利标识", False, f"HTTP状态码错误: {resp.status_code}")
259 + return False
260 +
261 + data = resp.json()
262 + if data.get('code') != 200:
263 + self.print_result("修改返利标识", False, f"业务状态码错误: {data.get('message', '未知错误')}")
264 + return False
265 +
266 + self.print_result("修改返利标识", True, f"成功修改返利标识: {self.test_product_id}")
267 +
268 + # 恢复返利标识
269 + resp2 = self.client.post(f'/api/product/{self.test_product_id}/rebate?rebateFlag=1', {})
270 +
271 + if resp2.status_code == 200:
272 + data2 = resp2.json()
273 + if data2.get('code') == 200:
274 + self.print_result("恢复返利标识", True, "成功恢复返利标识")
275 + else:
276 + self.print_result("恢复返利标识", False, f"恢复返利标识失败: {data2.get('message')}")
277 + else:
278 + self.print_result("恢复返利标识", False, f"恢复返利标识HTTP错误: {resp2.status_code}")
279 +
280 + return True
281 +
282 + except Exception as e:
283 + self.print_result("修改返利标识", False, f"异常: {str(e)}")
284 + return False
285 +
286 + def test_get_all_products(self) -> bool:
287 + """测试获取所有产品接口"""
288 + print("🔍 测试获取所有产品接口...")
289 +
290 + try:
291 + resp = self.client.get('/api/product/all')
292 +
293 + if resp.status_code != 200:
294 + self.print_result("获取所有产品", False, f"HTTP状态码错误: {resp.status_code}")
295 + return False
296 +
297 + data = resp.json()
298 + if data.get('code') != 200:
299 + self.print_result("获取所有产品", False, f"业务状态码错误: {data.get('message', '未知错误')}")
300 + return False
301 +
302 + # 检查响应结构
303 + products = data.get('data', [])
304 + if not isinstance(products, list):
305 + self.print_result("获取所有产品", False, "响应数据不是数组格式")
306 + return False
307 +
308 + # 检查产品字段
309 + if products:
310 + product = products[0]
311 + required_fields = ['productId', 'productCode', 'productName']
312 + for field in required_fields:
313 + if field not in product:
314 + self.print_result("获取所有产品", False, f"产品数据缺少{field}字段")
315 + return False
316 +
317 + self.print_result("获取所有产品", True, f"成功获取{len(products)}个产品")
318 + return True
319 +
320 + except Exception as e:
321 + self.print_result("获取所有产品", False, f"异常: {str(e)}")
322 + return False
323 +
324 + def test_batch_delete_products(self) -> bool:
325 + """测试批量删除产品接口"""
326 + print("🔍 测试批量删除产品接口...")
327 +
328 + if not self.test_product_ids:
329 + self.print_result("批量删除产品", False, "没有可用的产品ID进行测试")
330 + return False
331 +
332 + try:
333 + # 只删除测试创建的产品(通过产品编码识别)
334 + test_ids = []
335 + for product_id in self.test_product_ids:
336 + # 获取产品详情检查是否为测试产品
337 + detail_resp = self.client.get(f'/api/product/{product_id}')
338 + if detail_resp.status_code == 200:
339 + detail_data = detail_resp.json()
340 + if detail_data.get('code') == 200:
341 + product_detail = detail_data.get('data', {})
342 + if product_detail.get('productCode', '').startswith('TEST-'):
343 + test_ids.append(product_id)
344 +
345 + if not test_ids:
346 + self.print_result("批量删除产品", False, "没有找到测试产品进行删除")
347 + return False
348 +
349 + resp = self.client.post('/api/product/batchDelete', test_ids)
350 +
351 + if resp.status_code != 200:
352 + self.print_result("批量删除产品", False, f"HTTP状态码错误: {resp.status_code}")
353 + return False
354 +
355 + data = resp.json()
356 + if data.get('code') != 200:
357 + self.print_result("批量删除产品", False, f"业务状态码错误: {data.get('message', '未知错误')}")
358 + return False
359 +
360 + self.print_result("批量删除产品", True, f"成功删除{len(test_ids)}个测试产品")
361 + return True
362 +
363 + except Exception as e:
364 + self.print_result("批量删除产品", False, f"异常: {str(e)}")
365 + return False
366 +
367 + def test_delete_product(self) -> bool:
368 + """测试删除产品接口"""
369 + print("🔍 测试删除产品接口...")
370 +
371 + # 先创建一个测试产品用于删除
372 + timestamp = int(time.time())
373 + test_product_code = f"DELETE-TEST-{timestamp}"
374 +
375 + try:
376 + # 创建测试产品
377 + product_data = {
378 + "productCode": test_product_code,
379 + "productName": f"删除测试产品_{timestamp}",
380 + "productModel": "DELETE-TEST-MODEL",
381 + "productType": "删除测试类型",
382 + "saleStatus": 1,
383 + "rebateFlag": 1
384 + }
385 +
386 + create_resp = self.client.post('/api/product', product_data)
387 + if create_resp.status_code != 200:
388 + self.print_result("删除产品", False, "无法创建测试产品")
389 + return False
390 +
391 + create_data = create_resp.json()
392 + if create_data.get('code') != 200:
393 + self.print_result("删除产品", False, "无法创建测试产品")
394 + return False
395 +
396 + # 获取创建的产品ID
397 + list_resp = self.client.get('/api/product/list', {
398 + 'productCode': test_product_code,
399 + 'pageNum': 1,
400 + 'pageSize': 1
401 + })
402 +
403 + if list_resp.status_code != 200:
404 + self.print_result("删除产品", False, "无法获取测试产品ID")
405 + return False
406 +
407 + list_data = list_resp.json()
408 + if list_data.get('code') != 200 or not list_data.get('data', {}).get('records'):
409 + self.print_result("删除产品", False, "无法获取测试产品ID")
410 + return False
411 +
412 + delete_product_id = list_data['data']['records'][0].get('productId')
413 + if not delete_product_id:
414 + self.print_result("删除产品", False, "无法获取测试产品ID")
415 + return False
416 +
417 + # 删除产品
418 + resp = self.client.delete(f'/api/product/{delete_product_id}')
419 +
420 + if resp.status_code != 200:
421 + self.print_result("删除产品", False, f"HTTP状态码错误: {resp.status_code}")
422 + return False
423 +
424 + data = resp.json()
425 + if data.get('code') != 200:
426 + self.print_result("删除产品", False, f"业务状态码错误: {data.get('message', '未知错误')}")
427 + return False
428 +
429 + self.print_result("删除产品", True, f"成功删除产品ID: {delete_product_id}")
430 + return True
431 +
432 + except Exception as e:
433 + self.print_result("删除产品", False, f"异常: {str(e)}")
434 + return False
435 +
436 + def test_parameter_validation(self) -> bool:
437 + """测试参数验证"""
438 + print("🔍 测试参数验证...")
439 +
440 + try:
441 + # 测试必填字段验证
442 + invalid_data = {
443 + "productName": "测试产品",
444 + # 缺少必填字段 productCode, productModel, productType, saleStatus, rebateFlag
445 + }
446 +
447 + resp = self.client.post('/api/product', invalid_data)
448 +
449 + if resp.status_code == 200:
450 + data = resp.json()
451 + if data.get('code') != 200:
452 + self.print_result("参数验证", True, "正确返回参数验证错误")
453 + else:
454 + self.print_result("参数验证", False, "应该返回参数验证错误")
455 + return False
456 + else:
457 + self.print_result("参数验证", True, f"HTTP状态码正确: {resp.status_code}")
458 +
459 + # 测试无效的产品ID
460 + resp2 = self.client.get('/api/product/999999')
461 +
462 + if resp2.status_code == 200:
463 + data2 = resp2.json()
464 + if data2.get('code') != 200:
465 + self.print_result("无效ID验证", True, "正确返回产品不存在错误")
466 + else:
467 + self.print_result("无效ID验证", False, "应该返回产品不存在错误")
468 + return False
469 + else:
470 + self.print_result("无效ID验证", True, f"HTTP状态码正确: {resp2.status_code}")
471 +
472 + return True
473 +
474 + except Exception as e:
475 + self.print_result("参数验证", False, f"异常: {str(e)}")
476 + return False
477 +
478 + def run_all_tests(self) -> bool:
479 + """运行所有测试"""
480 + print("🚀 开始产品信息管理API测试")
481 + print("=" * 50)
482 +
483 + tests = [
484 + ("分页查询产品列表", self.test_list_products),
485 + ("获取产品详情", self.test_get_product_detail),
486 + ("新增产品", self.test_add_product),
487 + ("修改产品", self.test_update_product),
488 + ("修改返利标识", self.test_change_rebate_flag),
489 + ("获取所有产品", self.test_get_all_products),
490 + ("参数验证", self.test_parameter_validation),
491 + ("删除产品", self.test_delete_product),
492 + ("批量删除产品", self.test_batch_delete_products),
493 + ]
494 +
495 + passed = 0
496 + total = len(tests)
497 +
498 + for test_name, test_func in tests:
499 + try:
500 + if test_func():
501 + passed += 1
502 + except Exception as e:
503 + self.print_result(test_name, False, f"测试异常: {str(e)}")
504 +
505 + print("=" * 50)
506 + print(f"📊 测试结果: {passed}/{total} 通过")
507 +
508 + if passed == total:
509 + print("🎉 所有测试通过!")
510 + return True
511 + else:
512 + print("⚠️ 部分测试失败,请检查API实现")
513 + return False
514 +
515 +
516 +def main():
517 + """主函数"""
518 + if len(sys.argv) > 1 and sys.argv[1] == '--help':
519 + print("产品信息管理API测试工具")
520 + print("用法: python test_products.py")
521 + print("环境变量: API_BASE_URL (默认: http://localhost:8083)")
522 + return
523 +
524 + print("🚀 开始产品信息管理API测试")
525 + print("=" * 50)
526 +
527 + # 检查环境变量
528 + base_url = os.environ.get('API_BASE_URL', 'http://localhost:8083')
529 + print(f"API基础URL: {base_url}")
530 + print()
531 +
532 + # 创建测试器并运行测试
533 + tester = ProductApiTester()
534 + success = tester.run_all_tests()
535 +
536 + if success:
537 + print("🎉 所有产品API测试通过!")
538 + return 0
539 + else:
540 + print("⚠️ 部分产品API测试失败,请检查API实现")
541 + return 1
542 +
543 +
544 +if __name__ == '__main__':
545 + main()