Files
Yb-QaAutomationHub/tests/apis/yun8/driver_api.py
T
xst 52b73f456c 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 兼容
2026-09-08 11:38:17 +08:00

164 lines
6.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""司机端接口 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)