| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- # -*- coding: utf-8 -*-
- """客户端 api 第 2 批接口冒烟:购物车 / 结算下单 / 订单 / 订单评价 / 收货地址。
- 用法:起 Java 18080 后执行
- python tools/test_api_batch2.py
- 环境变量:YOSHOP_API_BASE(默认 http://127.0.0.1:18080)
- 说明:
- - 全部是需登录接口,脚本会往 Redis 写一个测试 token(yoshop:api:token:apitest-batch2);
- - 会真实下单,finally 中删除测试订单/订单商品/订单地址/评价并恢复库存与默认地址;
- - 数据库为联合调试库,测试商品固定取 10009(运费模板 10002,上海市 3 元运费)。
- """
- import json
- import os
- import re
- import socket
- import sys
- import pymysql
- import requests
- from _root import ROOT
- from redis_probe import cmd
- BASE = os.environ.get("YOSHOP_API_BASE", "http://127.0.0.1:18080")
- TOKEN = "apitest-batch2"
- USER_ID = 10001
- ADDRESS_ID = 10001
- # 测试商品:多规格、运费模板 10002(上海 +3 元、续件 +3 元)
- GOODS_ID = 10009
- SKU_ID = "10009"
- SKU_PRICE = "80.00"
- # 单规格包邮商品
- FREE_GOODS_ID = 10007
- FREE_SKU_ID = "0"
- FREE_SKU_PRICE = "39.90"
- YML = str(ROOT / "yoshop-java/src/main/resources/application.yml")
- TEXT = open(YML, encoding="utf-8").read()
- DB_PWD = re.findall(r"password:\s*(.+)", TEXT)[0].strip().strip("\"'")
- REDIS_PWD = re.findall(r"password:\s*(.+)", TEXT)[1].strip().strip("\"'")
- S = requests.Session()
- S.trust_env = False
- passed = 0
- failed = 0
- created_orders = []
- points_setting_created = False
- test_coupon_id = None
- stock_backup = {}
- address_backup = None
- def check(name, cond, detail=""):
- global passed, failed
- if cond:
- passed += 1
- print(f" PASS {name}")
- else:
- failed += 1
- print(f" FAIL {name} {detail}")
- def call(method, path, params=None, body=None, token=TOKEN):
- headers = {"platform": "MP-WEIXIN"}
- if token:
- headers["Access-Token"] = token
- if method == "GET":
- resp = S.get(BASE + path, params=params or {}, headers=headers, timeout=60)
- else:
- resp = S.post(BASE + path, params=params or {}, json=body, headers=headers, timeout=60)
- try:
- return resp.json()
- except Exception:
- return {"status": resp.status_code, "raw": resp.text[:300]}
- def get(path, params=None, token=TOKEN):
- return call("GET", path, params=params, token=token)
- def post(path, body=None, params=None, token=TOKEN):
- return call("POST", path, params=params, body=body, token=token)
- def snake_keys(obj, prefix="$"):
- found = []
- if isinstance(obj, dict):
- for k, v in obj.items():
- if isinstance(k, str) and re.fullmatch(r"[a-z0-9]+(_[a-z0-9]+)+", k):
- found.append(f"{prefix}.{k}")
- found.extend(snake_keys(v, f"{prefix}.{k}"))
- elif isinstance(obj, list):
- for i, v in enumerate(obj[:3]):
- found.extend(snake_keys(v, f"{prefix}[{i}]"))
- return found
- def db(sql):
- conn = pymysql.connect(host="192.168.1.177", port=3306, user="root", password=DB_PWD,
- database="shop", charset="utf8mb4", autocommit=True)
- try:
- cur = conn.cursor()
- cur.execute(sql)
- return cur.fetchall()
- finally:
- conn.close()
- def db_exec(sql):
- conn = pymysql.connect(host="192.168.1.177", port=3306, user="root", password=DB_PWD,
- database="shop", charset="utf8mb4", autocommit=True)
- try:
- cur = conn.cursor()
- cur.execute(sql)
- return cur.lastrowid
- finally:
- conn.close()
- def redis_set(key, value):
- sock = socket.create_connection(("192.168.1.177", 6379), timeout=5)
- try:
- cmd(sock, "AUTH", REDIS_PWD)
- cmd(sock, "SET", key, str(value))
- cmd(sock, "EXPIRE", key, "3600")
- finally:
- sock.close()
- def field(obj, name, default=None):
- return obj.get(name, default) if isinstance(obj, dict) else default
- def make_order(order_status, pay_status, delivery_status, receipt_status, is_comment=0, with_goods=True):
- """造一条测试订单,返回 order_id(订单商品取测试商品)"""
- order_no = "TEST" + str(os.getpid()) + str(len(created_orders))
- order_id = db_exec(
- "INSERT INTO yoshop_order (order_no, order_type, total_price, order_price, coupon_id, coupon_money, "
- "points_money, points_num, pay_price, update_price, buyer_remark, pay_method, pay_status, trade_id, "
- "delivery_type, express_price, delivery_status, receipt_status, order_status, points_bonus, "
- "is_settled, is_comment, order_source, order_source_id, order_source_data, platform, user_id, "
- "is_delete, store_id, create_time, update_time) VALUES "
- f"('{order_no}', 10, 80.00, 80.00, 0, 0.00, 0.00, 0, 83.00, 0.00, '', '', {pay_status}, 0, "
- f"10, 3.00, {delivery_status}, {receipt_status}, {order_status}, 0, 0, {is_comment}, 10, 0, '[]', "
- f"'H5', {USER_ID}, 0, 10001, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())")
- created_orders.append(order_id)
- if with_goods:
- db_exec(
- "INSERT INTO yoshop_order_goods (goods_id, goods_type, goods_name, image_id, deduct_stock_type, "
- "spec_type, goods_sku_id, goods_props, content, goods_no, goods_price, line_price, goods_weight, "
- "is_user_grade, grade_ratio, grade_goods_price, grade_total_money, coupon_money, points_money, "
- "points_num, points_bonus, total_num, total_price, total_pay_price, delivery_status, delivery_num, "
- "is_comment, order_id, user_id, goods_source_id, store_id, create_time) VALUES "
- f"({GOODS_ID}, 10, '正宗荔浦芋头', 0, 10, 20, '{SKU_ID}', '', '', '', 80.00, 100.00, 4.5, "
- f"0, 0, 0.00, 0.00, 0.00, 0.00, 0, 0, 1, 80.00, 80.00, 10, 0, 0, {order_id}, {USER_ID}, 0, "
- "10001, UNIX_TIMESTAMP())")
- return order_id
- def cleanup():
- try:
- ids = ",".join(str(i) for i in created_orders) or "0"
- db_exec(f"DELETE FROM yoshop_comment_image WHERE comment_id IN "
- f"(SELECT comment_id FROM yoshop_comment WHERE order_id IN ({ids}))")
- db_exec(f"DELETE FROM yoshop_comment WHERE order_id IN ({ids})")
- db_exec(f"DELETE FROM yoshop_order_goods WHERE order_id IN ({ids})")
- db_exec(f"DELETE FROM yoshop_order_address WHERE order_id IN ({ids})")
- db_exec(f"DELETE FROM yoshop_order WHERE order_id IN ({ids})")
- if stock_backup:
- db_exec(f"UPDATE yoshop_goods SET stock_total={stock_backup['stock_total']} WHERE goods_id={GOODS_ID}")
- db_exec(f"UPDATE yoshop_goods_sku SET stock_num={stock_backup['stock_num']} "
- f"WHERE goods_id={GOODS_ID} AND goods_sku_id='{SKU_ID}'")
- if address_backup is not None:
- db_exec(f"UPDATE yoshop_user SET address_id={address_backup} WHERE user_id={USER_ID}")
- db_exec(f"UPDATE yoshop_cart SET is_delete=1 WHERE user_id={USER_ID} AND goods_id={GOODS_ID}")
- if points_setting_created:
- db_exec("DELETE FROM yoshop_store_setting WHERE store_id=10001 AND `key`='points'")
- if test_coupon_id:
- db_exec("DELETE FROM yoshop_user_coupon WHERE name='接口自测券'")
- db_exec(f"UPDATE yoshop_user SET points=0 WHERE user_id={USER_ID}")
- db_exec(f"DELETE FROM yoshop_user_points_log WHERE user_id={USER_ID} AND `describe` LIKE '%接口自测%'")
- print(" CLEAN 测试数据已清理")
- except Exception as e: # noqa: BLE001
- print(" CLEAN 失败:", e)
- def main():
- global address_backup, points_setting_created, test_coupon_id
- print("== 客户端 api 第 2 批(购物车 / 结算下单 / 订单 / 评价 / 地址) ==")
- redis_set("yoshop:api:token:" + TOKEN, USER_ID)
- rows = db(f"SELECT address_id FROM yoshop_user WHERE user_id={USER_ID}")
- address_backup = rows[0][0] if rows else 0
- stock = db(f"SELECT stock_total FROM yoshop_goods WHERE goods_id={GOODS_ID}")[0][0]
- sku_stock = db(f"SELECT stock_num FROM yoshop_goods_sku WHERE goods_id={GOODS_ID} "
- f"AND goods_sku_id='{SKU_ID}'")[0][0]
- stock_backup.update(stock_total=stock, stock_num=sku_stock)
- db_exec(f"UPDATE yoshop_cart SET is_delete=1 WHERE user_id={USER_ID}")
- # ---------------------------------------------------------------- 未登录
- r = get("/api/cart/list", token=None)
- check("未登录购物车返回 401", r.get("status") == 401, r.get("message"))
- # ---------------------------------------------------------------- 收货地址
- print("-- 收货地址")
- r = get("/api/address/list")
- check("address/list status=200", r.get("status") == 200, r.get("message"))
- addr_list = field(r.get("data"), "list") or []
- check("address/list 是数组且含默认地址", any(a.get("addressId") == ADDRESS_ID for a in addr_list), addr_list)
- check("地址节点无 snake_case", not snake_keys(addr_list), snake_keys(addr_list)[:3])
- r = post("/api/address/add", {
- "name": "接口自测", "phone": "13800000000", "detail": "自测详细地址",
- "region": [{"value": 110000}, {"value": 110100}, {"value": 110101}],
- })
- check("address/add 添加成功", r.get("status") == 200 and r.get("message") == "添加成功", r)
- new_id = db(f"SELECT MAX(address_id) FROM yoshop_user_address WHERE user_id={USER_ID}")[0][0]
- row = db(f"SELECT name, province_id, city_id, region_id FROM yoshop_user_address WHERE address_id={new_id}")[0]
- check("address/add 省市区解析正确", tuple(row[1:]) == (110000, 110100, 110101), row)
- r = get("/api/address/default_id")
- check("address/default_id 原默认地址不变", field(r.get("data"), "defaultId") == ADDRESS_ID,
- r.get("data"))
- r = get("/api/address/detail", {"addressId": new_id})
- check("address/detail 返回新地址", field(field(r.get("data"), "detail"), "name") == "接口自测", r.get("data"))
- r = post("/api/address/edit", {
- "addressId": new_id, "name": "接口自测2", "phone": "13900000000", "detail": "改后地址",
- "region": [{"value": 310000}, {"value": 310100}, {"value": 310104}],
- })
- check("address/edit 更新成功", r.get("status") == 200 and r.get("message") == "更新成功", r)
- row = db(f"SELECT name, province_id, city_id FROM yoshop_user_address WHERE address_id={new_id}")[0]
- check("address/edit 已落库", row == ("接口自测2", 310000, 310100), row)
- r = post("/api/address/set_default", {"addressId": new_id})
- check("address/set_default 设置成功", r.get("status") == 200, r)
- check("address/set_default 落库", db(f"SELECT address_id FROM yoshop_user WHERE user_id={USER_ID}")[0][0] == new_id)
- r = post("/api/address/add", {"name": "缺省市区"})
- check("address/add 缺省市区报错", r.get("status") == 500, r)
- r = post("/api/address/remove", {"addressId": new_id})
- check("address/remove 删除成功", r.get("status") == 200 and r.get("message") == "删除成功", r)
- check("address/remove 清空默认地址", db(f"SELECT address_id FROM yoshop_user WHERE user_id={USER_ID}")[0][0] == 0)
- db_exec(f"UPDATE yoshop_user SET address_id={ADDRESS_ID} WHERE user_id={USER_ID}")
- r = get("/api/address/detail", {"addressId": new_id})
- check("address/detail 已删除不可见", r.get("status") == 500, r)
- # ---------------------------------------------------------------- 购物车
- print("-- 购物车")
- r = get("/api/cart/list")
- check("cart/list status=200", r.get("status") == 200, r.get("message"))
- check("cart/list 初始 cartTotal=0", field(r.get("data"), "cartTotal") == 0, r.get("data"))
- r = post("/api/cart/add", {"goodsId": GOODS_ID, "goodsSkuId": SKU_ID, "goodsNum": 1})
- check("cart/add 加入购物车", r.get("status") == 200 and field(r.get("data"), "cartTotal") == 1, r)
- r = post("/api/cart/add", {"goodsId": GOODS_ID, "goodsSkuId": SKU_ID, "goodsNum": 1})
- check("cart/add 同规格累加数量", field(r.get("data"), "cartTotal") == 2, r.get("data"))
- r = get("/api/cart/list")
- cart_list = field(r.get("data"), "list") or []
- check("cart/list 一条记录", len(cart_list) == 1, len(cart_list))
- if cart_list:
- item = cart_list[0]
- goods = field(item, "goods") or {}
- check("cart/list 含 goods.skuInfo", field(goods, "skuInfo") is not None, list(goods))
- check("cart/list skuInfo.goodsPrice 正确",
- str(field(field(goods, "skuInfo"), "goodsPrice")) == SKU_PRICE, field(goods, "skuInfo"))
- check("cart/list 记录隐藏 storeId/createTime",
- not ({"storeId", "createTime", "isDelete"} & set(item)), list(item))
- check("cart/list 无 snake_case 键", not snake_keys(cart_list), snake_keys(cart_list)[:3])
- r = post("/api/cart/update", {"goodsId": GOODS_ID, "goodsSkuId": SKU_ID, "goodsNum": 3})
- check("cart/update 更新数量", field(r.get("data"), "cartTotal") == 3, r.get("data"))
- check("cart/update 落库", db(f"SELECT goods_num FROM yoshop_cart WHERE user_id={USER_ID} "
- f"AND is_delete=0 AND goods_id={GOODS_ID}")[0][0] == 3)
- r = get("/api/cart/total")
- check("cart/total 返回 3", field(r.get("data"), "cartTotal") == 3, r.get("data"))
- r = post("/api/cart/add", {"goodsId": 999999, "goodsSkuId": "0", "goodsNum": 1})
- check("cart/add 商品不存在报错", r.get("status") == 500, r)
- r = post("/api/cart/add", {"goodsId": GOODS_ID, "goodsSkuId": SKU_ID, "goodsNum": 99999})
- check("cart/add 超库存报错", r.get("status") == 500 and "库存" in (r.get("message") or ""), r)
- # ---------------------------------------------------------------- 结算台
- print("-- 结算台")
- r = get("/api/checkout/order", {"mode": "buyNow", "goodsId": FREE_GOODS_ID,
- "goodsSkuId": FREE_SKU_ID, "goodsNum": 2})
- order = field(r.get("data"), "order") or {}
- check("checkout 包邮商品订单总额", order.get("orderTotalPrice") == "79.80", order.get("orderTotalPrice"))
- check("checkout 包邮运费 0.00", order.get("expressPrice") == "0.00", order.get("expressPrice"))
- check("checkout 含 personal/setting", {"personal", "setting"} <= set(r.get("data") or {}), list(r.get("data") or {}))
- check("checkout personal 四项",
- set(field(r.get("data"), "personal") or {}) == {"userId", "balance", "points", "addressId"},
- field(r.get("data"), "personal"))
- check("checkout setting 三项",
- set(field(r.get("data"), "setting") or {}) == {"deliveryType", "pointsName", "pointsDescribe"},
- field(r.get("data"), "setting"))
- check("checkout 有地址且 isIntraRegion", order.get("existAddress") is True and order.get("isIntraRegion") is True,
- order.get("existAddress"))
- r = get("/api/checkout/order", {"mode": "buyNow", "goodsId": GOODS_ID,
- "goodsSkuId": SKU_ID, "goodsNum": 1})
- order = field(r.get("data"), "order") or {}
- check("checkout 首件运费 3.00", order.get("expressPrice") == "3.00", order.get("expressPrice"))
- check("checkout 订单实付 83.00", order.get("orderPayPrice") == "83.00", order.get("orderPayPrice"))
- check("checkout 商品行字段完整", {"goodsPrice", "totalNum", "totalPrice", "totalPayPrice", "skuInfo"}
- <= set((order.get("goodsList") or [{}])[0]), list((order.get("goodsList") or [{}])[0]))
- r = get("/api/checkout/order", {"mode": "buyNow", "goodsId": GOODS_ID,
- "goodsSkuId": SKU_ID, "goodsNum": 2})
- order = field(r.get("data"), "order") or {}
- check("checkout 续件运费 6.00", order.get("expressPrice") == "6.00", order.get("expressPrice"))
- check("checkout 续件实付 166.00", order.get("orderPayPrice") == "166.00", order.get("orderPayPrice"))
- check("checkout 无 snake_case 键", not snake_keys(r.get("data")), snake_keys(r.get("data"))[:3])
- r = get("/api/checkout/order", {"mode": "cart", "cartIds": ",".join(
- str(x[0]) for x in db(f"SELECT id FROM yoshop_cart WHERE user_id={USER_ID} AND is_delete=0"))})
- order = field(r.get("data"), "order") or {}
- check("checkout 购物车模式商品数 3", order.get("orderTotalNum") == 3, order.get("orderTotalNum"))
- check("checkout 购物车模式总额 240.00", order.get("orderTotalPrice") == "240.00", order.get("orderTotalPrice"))
- r = get("/api/checkout/order", {"mode": "buyNow", "goodsId": GOODS_ID,
- "goodsSkuId": SKU_ID, "goodsNum": 99999})
- order = field(r.get("data"), "order") or {}
- check("checkout 超库存 hasError", order.get("hasError") is True and "库存" in (order.get("errorMsg") or ""),
- order.get("errorMsg"))
- r = get("/api/checkout/order", {"mode": "unknown"})
- check("checkout 非法模式报错", r.get("status") == 500, r.get("message"))
- # ---------------------------------------------------------------- 下单
- print("-- 下单")
- before = db(f"SELECT stock_total FROM yoshop_goods WHERE goods_id={GOODS_ID}")[0][0]
- r = post("/api/checkout/submit", {"mode": "buyNow", "goodsId": GOODS_ID,
- "goodsSkuId": SKU_ID, "goodsNum": 1, "remark": "接口自测"})
- order_id = field(r.get("data"), "orderId")
- check("checkout/submit 下单成功", r.get("status") == 200 and order_id, r)
- if not order_id:
- print(f"\n结果:PASS {passed} / FAIL {failed}(下单失败,后续订单断言跳过)")
- return 1
- created_orders.append(order_id)
- row = db(f"SELECT order_no, user_id, order_status, pay_status, delivery_type, express_price, "
- f"pay_price, buyer_remark, is_delete FROM yoshop_order WHERE order_id={order_id}")[0]
- check("订单已落库且待支付", row[2] == 10 and row[3] == 10, row)
- check("订单运费 3.00 / 实付 83.00", str(row[5]) == "3.00" and str(row[6]) == "83.00", row)
- check("订单备注已保存", row[7] == "接口自测", row[7])
- goods_row = db(f"SELECT goods_id, goods_sku_id, goods_price, total_num, total_price, total_pay_price "
- f"FROM yoshop_order_goods WHERE order_id={order_id}")[0]
- check("订单商品已落库", goods_row[0] == GOODS_ID and str(goods_row[2]) == SKU_PRICE and goods_row[3] == 1, goods_row)
- check("订单收货地址已落库", db(f"SELECT COUNT(*) FROM yoshop_order_address WHERE order_id={order_id}")[0][0] == 1)
- after = db(f"SELECT stock_total FROM yoshop_goods WHERE goods_id={GOODS_ID}")[0][0]
- check("下单扣减商品库存", after == before - 1, (before, after))
- # ---------------------------------------------------------------- 订单接口
- print("-- 订单")
- r = get("/api/order/detail", {"orderId": order_id})
- detail = field(r.get("data"), "order") or {}
- check("order/detail status=200", r.get("status") == 200, r.get("message"))
- check("order/detail 含 goods/address/stateText", {"goods", "address", "stateText"} <= set(detail), list(detail))
- check("order/detail 隐藏 merchantRemark/tradeId/isDelete",
- not ({"merchantRemark", "tradeId", "isDelete", "storeId"} & set(detail)), list(detail))
- check("order/detail 商品隐藏 image/content",
- not ({"image", "content", "storeId"} & set((detail.get("goods") or [{}])[0])),
- list((detail.get("goods") or [{}])[0]))
- check("order/detail setting.pointsName 键存在", "pointsName" in (field(r.get("data"), "setting") or {}))
- check("order/detail 无 snake_case 键", not snake_keys(r.get("data")), snake_keys(r.get("data"))[:3])
- r = get("/api/order/list", {"dataType": "payment"})
- page = field(r.get("data"), "list") or {}
- ids = [o.get("orderId") for o in (page.get("data") or [])]
- check("order/list 待付款含新订单", order_id in ids, ids)
- check("order/list 分页字段 perPage=15", page.get("perPage") == 15, page.get("perPage"))
- r = get("/api/order/todo_counts")
- counts = field(r.get("data"), "counts") or {}
- check("order/todo_counts 四个键", set(counts) == {"payment", "delivery", "received", "refund"}, counts)
- check("order/todo_counts 待付款 >=1", counts.get("payment", 0) >= 1, counts)
- r = get("/api/order/express", {"orderId": order_id})
- check("order/express 未发货返回空数组", r.get("status") == 200 and r.get("data") == {"express": []}, r.get("data"))
- r = post("/api/order/cancel", {"orderId": order_id})
- check("order/cancel 未支付订单取消成功",
- r.get("status") == 200 and r.get("message") == "订单已取消成功", r)
- check("order/cancel 订单状态 20",
- db(f"SELECT order_status FROM yoshop_order WHERE order_id={order_id}")[0][0] == 20)
- check("order/cancel 回滚库存",
- db(f"SELECT stock_total FROM yoshop_goods WHERE goods_id={GOODS_ID}")[0][0] == before)
- # 收货:造已发货订单
- receipt_order = make_order(10, 20, 20, 10)
- r = post("/api/order/receipt", {"orderId": receipt_order})
- check("order/receipt 确认收货成功", r.get("status") == 200 and r.get("message") == "确认收货成功", r)
- row = db(f"SELECT order_status, receipt_status FROM yoshop_order WHERE order_id={receipt_order}")[0]
- check("order/receipt 状态已更新", row == (30, 20), row)
- r = post("/api/order/receipt", {"orderId": receipt_order})
- check("order/receipt 重复收货报错", r.get("status") == 500 and "不合法" in (r.get("message") or ""), r)
- r = get("/api/order/detail", {"orderId": 99999999})
- check("order/detail 不存在报错", r.get("status") == 500 and "订单不存在" in (r.get("message") or ""), r)
- # ---------------------------------------------------------------- 订单评价
- print("-- 订单评价")
- comment_order = make_order(30, 20, 20, 20)
- r = get("/api/order.comment/list", {"orderId": comment_order})
- goods_list = field(r.get("data"), "goodsList") or []
- check("order.comment/list 待评价商品 1 条", len(goods_list) == 1, len(goods_list))
- order_goods_id = field(goods_list[0], "orderGoodsId") if goods_list else None
- check("order.comment/list 商品含 goodsImage", "goodsImage" in (goods_list[0] if goods_list else {}))
- r = post("/api/order.comment/submit", [
- {"orderGoodsId": order_goods_id, "goodsId": GOODS_ID, "score": 10,
- "content": "接口自测评价", "uploaded": []},
- ], params={"orderId": comment_order})
- check("order.comment/submit 评价成功", r.get("status") == 200 and r.get("message") == "评价发表成功", r)
- check("评价已落库", db(f"SELECT content FROM yoshop_comment WHERE order_id={comment_order}")[0][0] == "接口自测评价")
- check("订单商品标记已评价",
- db(f"SELECT is_comment FROM yoshop_order_goods WHERE order_id={comment_order}")[0][0] == 1)
- check("订单标记已评价", db(f"SELECT is_comment FROM yoshop_order WHERE order_id={comment_order}")[0][0] == 1)
- r = get("/api/order.comment/list", {"orderId": comment_order})
- check("已评价后列表报错", r.get("status") == 500 and "已完成评价" in (r.get("message") or ""), r)
- # 未完成订单不可评价
- pending_order = make_order(10, 10, 10, 10)
- r = get("/api/order.comment/list", {"orderId": pending_order})
- check("未完成订单不可评价", r.get("status") == 500 and "未完成" in (r.get("message") or ""), r)
- # ---------------------------------------------------------------- 优惠券 + 积分抵扣
- print("-- 优惠券与积分抵扣(临时造数据)")
- points_setting = json.dumps({
- "pointsName": "积分", "describe": "接口自测",
- "isShoppingDiscount": 1, "isShoppingGift": 1, "giftRatio": 100,
- "discount": {"fullOrderPrice": 0, "maxMoneyRatio": 100, "discountRatio": 0.01},
- }, ensure_ascii=False)
- db_exec("INSERT INTO yoshop_store_setting (`key`, `describe`, `values`, store_id, create_time, update_time) "
- f"VALUES ('points', '积分设置', '{points_setting}', 10001, 0, UNIX_TIMESTAMP())")
- points_setting_created = True
- db_exec(f"UPDATE yoshop_user SET points=1000 WHERE user_id={USER_ID}")
- coupon_row = db_exec(
- "INSERT INTO yoshop_user_coupon (coupon_id, name, coupon_type, reduce_price, discount, min_price, "
- "expire_type, expire_day, start_time, end_time, apply_range, apply_range_config, `describe`, "
- "is_expire, is_use, user_id, store_id, create_time, update_time) VALUES "
- "(0, '接口自测券', 10, 5.00, 0, 0.00, 10, 30, UNIX_TIMESTAMP()-3600, UNIX_TIMESTAMP()+86400, "
- f"10, '{{\"goodsIds\":[]}}', '', 0, 0, {USER_ID}, 10001, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())")
- test_coupon_id = db(f"SELECT user_coupon_id FROM yoshop_user_coupon WHERE name='接口自测券'")[0][0]
- r = get("/api/checkout/order", {"mode": "buyNow", "goodsId": GOODS_ID, "goodsSkuId": SKU_ID,
- "goodsNum": 1, "couponId": test_coupon_id, "isUsePoints": 1})
- order = field(r.get("data"), "order") or {}
- check("结算台返回可用优惠券", len(order.get("couponList") or []) >= 1, order.get("couponList"))
- check("优惠券抵扣 5.00", order.get("couponMoney") == "5.00", order.get("couponMoney"))
- check("积分可抵扣 isAllowPoints", order.get("isAllowPoints") is True, order.get("isAllowPoints"))
- check("积分抵扣数量 1000", order.get("pointsNum") == 1000, order.get("pointsNum"))
- check("积分抵扣金额 10.00", order.get("pointsMoney") == "10.00", order.get("pointsMoney"))
- check("订单金额 65.00 / 实付 68.00",
- order.get("orderPrice") == "65.00" and order.get("orderPayPrice") == "68.00",
- (order.get("orderPrice"), order.get("orderPayPrice")))
- check("赠送积分 65", order.get("pointsBonus") == 65, order.get("pointsBonus"))
- line = (order.get("goodsList") or [{}])[0]
- check("商品行优惠券/积分/实付",
- line.get("couponMoney") == "5.00" and line.get("pointsMoney") == "10.00"
- and line.get("totalPayPrice") == "65.00",
- (line.get("couponMoney"), line.get("pointsMoney"), line.get("totalPayPrice")))
- r = post("/api/checkout/submit", {"mode": "buyNow", "goodsId": GOODS_ID, "goodsSkuId": SKU_ID,
- "goodsNum": 1, "couponId": test_coupon_id, "isUsePoints": 1})
- coupon_order = field(r.get("data"), "orderId")
- check("带优惠券+积分下单成功", r.get("status") == 200 and coupon_order, r)
- if coupon_order:
- created_orders.append(coupon_order)
- row = db(f"SELECT coupon_id, coupon_money, points_money, points_num, pay_price, points_bonus "
- f"FROM yoshop_order WHERE order_id={coupon_order}")[0]
- check("订单优惠券已落库", row[0] == test_coupon_id and str(row[1]) == "5.00", row)
- check("订单积分抵扣已落库", str(row[2]) == "10.00" and row[3] == 1000, row)
- check("订单实付 68.00 / 赠送积分 65", str(row[4]) == "68.00" and row[5] == 65, row)
- check("优惠券已核销",
- db(f"SELECT is_use FROM yoshop_user_coupon WHERE user_coupon_id={test_coupon_id}")[0][0] == 1)
- check("用户积分已扣减 1000→0", db(f"SELECT points FROM yoshop_user WHERE user_id={USER_ID}")[0][0] == 0)
- check("积分流水已记录",
- db(f"SELECT COUNT(*) FROM yoshop_user_points_log WHERE user_id={USER_ID} AND value=-1000")[0][0] >= 1)
- r = post("/api/order/cancel", {"orderId": coupon_order})
- check("取消订单成功", r.get("status") == 200, r)
- check("取消回退积分", db(f"SELECT points FROM yoshop_user WHERE user_id={USER_ID}")[0][0] == 1000)
- check("取消回退优惠券",
- db(f"SELECT is_use FROM yoshop_user_coupon WHERE user_coupon_id={test_coupon_id}")[0][0] == 0)
- print(f"\n结果:PASS {passed} / FAIL {failed}")
- return 1 if failed else 0
- if __name__ == "__main__":
- code = 1
- try:
- code = main()
- finally:
- cleanup()
- sys.exit(code)
|