refactor(api): yun8_sync 并入 tests 分层框架(接口层 apis/yun8 + 用例层 api + Allure)
- tests/core: 新增 BaseHttpClient 统一 HTTP 封装(直连绕行/超时/日志/自定义编码); db_helper 追加 Db 长连接类(事务/mogrify/自动重连),既有函数不动 - tests/apis/yun8: 21 个 step 方法按域拆分为 5 个 Mixin(driver/accounting/ audit_payment/receipt/third_party),Yun8Pipeline 24 步编排原样迁移, SQL 全部参数化并集中至 sql_templates - tests/api: 5 阶段有序 P0 E2E 用例(业务失败由 print 改为真实报错)+ README 迁移(删除明文密码段,修正步骤编号漂移) - yun8_sync 目录退役:配置并入 test_config.yaml 的 yun8_api 段; 造数 CLI 保留(python -m tests.apis.yun8.cli,兼容旧 config.yaml 结构) - pytest.ini 注册 api/yun8_sync marker;requirements.txt 补 requests>=2.28 - 静态验证: compileall / 全仓 collect 24 条 / marker 过滤 / CLI --help / 客户端与 pipeline 离线实例化 / SQL 占位符核对 / cross_end 兼容
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
"""司机端接口 Mixin — step01-05(对应 Postman Collection 司机端 5 个接口)。
|
||||
|
||||
所有方法签名/返回值/默认值与旧 yun8_sync/client.py 逐字一致,
|
||||
仅将原始 requests.Session 调用替换为 BaseHttpClient(self.driver_http)。
|
||||
|
||||
Usage:
|
||||
from tests.apis.yun8.driver_api import DriverApi
|
||||
class Yun8ApiClient(DriverApi, ...): ...
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from tests.core.http_client import BaseHttpClient
|
||||
|
||||
|
||||
def _current_time_str() -> str:
|
||||
"""Postman pre-request: 生成 'YYYY-MM-DD HH:MM:SS' 格式的当前时间"""
|
||||
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
|
||||
class DriverApi:
|
||||
"""司机端接口(挂载于 Yun8ApiClient,依赖 driver_http / dp 属性)。"""
|
||||
|
||||
# ==================================================================
|
||||
# Step 01: 查询货源
|
||||
# ==================================================================
|
||||
def step01_query_goods(self, page_size: int = 10, page_num: int = 1) -> dict:
|
||||
"""
|
||||
Postman Test Script:
|
||||
pm.collectionVariables.set("mainOrderCode", jsonData.data.records[0].code);
|
||||
pm.collectionVariables.set("residueNumber", jsonData.data.records[0].lastWeight);
|
||||
|
||||
Returns: {"mainOrderCode": str, "residueNumber": str}
|
||||
"""
|
||||
params = {
|
||||
"isFromOrderHall": "1",
|
||||
"sortType": "desc",
|
||||
"sortField": "gmt_created",
|
||||
"pageSize": page_size,
|
||||
"pageNum": page_num,
|
||||
}
|
||||
data = self.driver_http.get("/ntocc-tms-api/order/orderHallList", params)
|
||||
records = data.get("data", {}).get("records", [])
|
||||
if not records:
|
||||
raise RuntimeError("查询货源: 无记录返回")
|
||||
|
||||
r = records[0]
|
||||
return {
|
||||
"mainOrderCode": r.get("code", ""),
|
||||
"residueNumber": str(r.get("lastWeight", "")),
|
||||
"shipperLatitude": str(r.get("shipperLatitude", "")),
|
||||
"shipperLongitude": str(r.get("shipperLongitude", "")),
|
||||
"consigneeLatitude": str(r.get("consigneeLatitude", "")),
|
||||
"consigneeLongitude": str(r.get("consigneeLongitude", "")),
|
||||
}
|
||||
|
||||
# ==================================================================
|
||||
# Step 02: 接单
|
||||
# ==================================================================
|
||||
def step02_accept_order(self, main_order_code: str, residue_number: str,
|
||||
message_code: str = "",
|
||||
latitude: str = None, longitude: str = None) -> dict:
|
||||
"""
|
||||
Postman Body (urlencoded):
|
||||
residueNumber / perWeight / latitude / messageCode / mainOrderCode / longitude
|
||||
latitude/longitude 优先取货源接口的 shipperLat/shipperLng,没有则用 config
|
||||
"""
|
||||
data = {
|
||||
"residueNumber": residue_number,
|
||||
"perWeight": self.dp.get("per_weight", "1"),
|
||||
"latitude": latitude or self.dp.get("latitude", ""),
|
||||
"messageCode": message_code,
|
||||
"mainOrderCode": main_order_code,
|
||||
"longitude": longitude or self.dp.get("longitude", ""),
|
||||
}
|
||||
return self.driver_http.post("/ntocc-tms-api/orderDetail/receive", data=data)
|
||||
|
||||
# ==================================================================
|
||||
# Step 03: 查询待运输单
|
||||
# ==================================================================
|
||||
def step03_query_pending_transport(self, page_size: int = 10, page_num: int = 1) -> dict:
|
||||
"""
|
||||
Postman Test Script:
|
||||
pm.collectionVariables.set("code", jsonData.data.records[0].code);
|
||||
pm.collectionVariables.set("vehicleCode", jsonData.data.records[0].vehicleCode);
|
||||
pm.collectionVariables.set("orderCode", jsonData.data.records[0].orderCode);
|
||||
|
||||
Returns: {"code": str, "vehicleCode": str, "orderCode": str}
|
||||
"""
|
||||
params = {
|
||||
"assignmentStatus": "waitTrans",
|
||||
"placeOfReceipt": "",
|
||||
"gmtCreatedEnd": "",
|
||||
"gmtCreatedStart": "",
|
||||
"pageSize": page_size,
|
||||
"placeOfShipment": "",
|
||||
"pageNum": page_num,
|
||||
"shipmentName": "",
|
||||
"status": "1",
|
||||
"vehicleLicense": "",
|
||||
}
|
||||
data = self.driver_http.get("/ntocc-tms-api/orderDetail", params)
|
||||
records = data.get("data", {}).get("records", [])
|
||||
if not records:
|
||||
raise RuntimeError("查询待运输单: 无记录返回")
|
||||
|
||||
r = records[0]
|
||||
return {
|
||||
"code": r.get("code", ""),
|
||||
"vehicleCode": r.get("vehicleCode", ""),
|
||||
"orderCode": r.get("orderCode", ""),
|
||||
}
|
||||
|
||||
# ==================================================================
|
||||
# Step 04: 装货
|
||||
# ==================================================================
|
||||
def step04_load_goods(self, code: str, vehicle_code: str,
|
||||
img_url: str = "", quantity: str = "",
|
||||
weight: str = None,
|
||||
latitude: str = None, longitude: str = None) -> dict:
|
||||
"""
|
||||
Postman Pre-request Script: 生成 currentTime
|
||||
Body: imgUrl / orderType / quantity / code / latitude / weight / vehicleCode / time / longitude
|
||||
latitude/longitude 优先取货源接口的 shipperLat/shipperLng
|
||||
"""
|
||||
if weight is None:
|
||||
weight = self.dp.get("weight", "1")
|
||||
body = {
|
||||
"imgUrl": img_url or self.dp.get("load_img_url", ""),
|
||||
"orderType": "1",
|
||||
"quantity": quantity,
|
||||
"code": code,
|
||||
"latitude": latitude or self.dp.get("latitude", ""),
|
||||
"weight": weight,
|
||||
"vehicleCode": vehicle_code,
|
||||
"time": _current_time_str(),
|
||||
"longitude": longitude or self.dp.get("longitude", ""),
|
||||
}
|
||||
return self.driver_http.put("/ntocc-tms-api/orderDetail/fill", data=body)
|
||||
|
||||
# ==================================================================
|
||||
# Step 05: 卸货
|
||||
# ==================================================================
|
||||
def step05_unload_goods(self, code: str, img_url: str = "",
|
||||
quantity: str = "", weight: str = None,
|
||||
latitude: str = None, longitude: str = None) -> dict:
|
||||
"""
|
||||
Postman Pre-request Script: 生成 currentTime
|
||||
Body: imgUrl / code / quantity / latitude / weight / time / longitude
|
||||
latitude/longitude 优先取货源接口的 consigneeLat/consigneeLng
|
||||
"""
|
||||
if weight is None:
|
||||
weight = self.dp.get("weight", "1")
|
||||
body = {
|
||||
"imgUrl": img_url or self.dp.get("unload_img_url", ""),
|
||||
"code": code,
|
||||
"quantity": quantity,
|
||||
"latitude": latitude or self.dp.get("latitude", ""),
|
||||
"weight": weight,
|
||||
"time": _current_time_str(),
|
||||
"longitude": longitude or self.dp.get("longitude", ""),
|
||||
}
|
||||
return self.driver_http.put("/ntocc-tms-api/orderDetail/uploadTicketImage", data=body)
|
||||
Reference in New Issue
Block a user