三条断言跟上新文案:冻结来路分开、判据码显示层剥掉、接口地址只进日志

三条钉的都是旧写法,而且都是这批要改掉的东西:
- 冻结原因原先断言以「禁增持」结尾,现在按三种来路分开写,改成断言语义并加一条
  禁止枚举值出现的检查。
- 行业名额那条原先断言消息里含 SECTOR_NAMES,现在判据码在显示层被剥掉了(码仍
  留在句首供账本去重与原因聚类用),改成按中文关键词断言。
- 取数报错那条原先断言消息里带接口地址,那正是把排查信息塞给用户看的写法。改成
  断言消息里说清「选股系统」怎么了,同时断言接口地址、异常类名、异常原文一个都
  不许出现。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
zlt 2026-09-04 13:31:30 +08:00
parent 4077b57e35
commit 06fcc552bd
3 changed files with 29 additions and 4 deletions

View File

@ -190,7 +190,9 @@ def _():
caps=caps(sector_max_names=1), room_amt=1_400_000, slots=20) caps=caps(sector_max_names=1), room_amt=1_400_000, slots=20)
assert len(r["candidates"]) == 1, [c["ts_code"] for c in r["candidates"]] assert len(r["candidates"]) == 1, [c["ts_code"] for c in r["candidates"]]
whys = " ".join(s["why"] for s in r["skipped"]) whys = " ".join(s["why"] for s in r["skipped"])
assert "SECTOR_NAMES" in whys, whys # 2026-09-04 起判据码在显示层被剥掉了 (码仍留在句首供账本去重与原因聚类用),
# 所以这里按中文关键词断言, 不按码。
assert "同一行业" in whys and "只的上限" in whys, whys
@case("新建仓·行业数据源没配时不误拦 (sector 一律按空处理)") @case("新建仓·行业数据源没配时不误拦 (sector 一律按空处理)")

View File

@ -229,7 +229,14 @@ def _():
assert ("600000.SH", "TRIM") in acts, acts # 冻结不挡减仓 assert ("600000.SH", "TRIM") in acts, acts # 冻结不挡减仓
assert not any(c[0] == "600000.SH" and c[1] != "TRIM" for c in acts), acts assert not any(c[0] == "600000.SH" and c[1] != "TRIM" for c in acts), acts
assert ("000001.SZ", "ADD") in acts, acts assert ("000001.SZ", "ADD") in acts, acts
assert any(s["why"].endswith("禁增持") for s in r["skipped"]), r["skipped"] # 2026-09-04 起这句话按冻结的三种来路分开写, 不再印枚举值。三种来路对交易员是
# 三件不同的事: 你下的命令、你手设的、系统刹车期间。
assert all("只卖不买" in s["why"] and "不评估加仓" in s["why"]
for s in r["skipped"]), r["skipped"]
assert any("你下过命令" in s["why"] for s in r["skipped"]), r["skipped"]
for s in r["skipped"]: # 枚举值不许再出现在给人看的句子里
for w in ("COMMAND_HALT", "MANUAL", "BRAKE"):
assert w not in s["why"], s["why"]
r2 = ae.scan(positions=ps, params=PARAMS, r2 = ae.scan(positions=ps, params=PARAMS,
market={"600000.SH": mkt(), "000001.SZ": mkt(ma5=10.6, high5=11.0), market={"600000.SH": mkt(), "000001.SZ": mkt(ma5=10.6, high5=11.0),

View File

@ -611,19 +611,35 @@ def _():
assert calls2[0]["params"] is None, calls2 assert calls2[0]["params"] is None, calls2
@case("取数·HTTP 报错/JSON 坏掉一律包装成 PlanFeedError 并带上 URL") @case("取数·HTTP 报错/JSON 坏掉一律包装成 PlanFeedError, 消息给人看、接口地址进日志")
def _(): def _():
# 这条消息会渲染成页面顶部整条红色横幅, 交易员一进页面就看到。所以:
# 句子里不许有接口地址、异常类名、异常原文 —— 那些只进运行日志;
# 句子里必须说清现在拿不到什么, 让人知道发生了什么。
# 2026-09-04 之前这里断言消息里带 URL, 那正是把排查信息塞给用户看的写法。
import logging
for handler in (lambda *a: _FakeResp(SAMPLE, status=500), for handler in (lambda *a: _FakeResp(SAMPLE, status=500),
lambda *a: _FakeResp(ValueError("Expecting value")), lambda *a: _FakeResp(ValueError("Expecting value")),
lambda *a: (_ for _ in ()).throw(OSError("Connection refused"))): lambda *a: (_ for _ in ()).throw(OSError("Connection refused"))):
calls, restore = _with_fake_requests(handler) calls, restore = _with_fake_requests(handler)
logged = []
h = logging.Handler()
h.emit = lambda rec: logged.append(rec.getMessage() if not rec.args
else rec.msg % rec.args)
lg = logging.getLogger("pms.plan")
lg.addHandler(h)
try: try:
try: try:
pf.fetch(base="http://192.168.16.155:8300", path="/plan", timeout=1) pf.fetch(base="http://192.168.16.155:8300", path="/plan", timeout=1)
raise AssertionError("应当抛 PlanFeedError") raise AssertionError("应当抛 PlanFeedError")
except pf.PlanFeedError as e: except pf.PlanFeedError as e:
assert "192.168.16.155:8300/plan" in str(e), str(e) msg = str(e)
assert "选股系统" in msg, msg
for bad in ("192.168.16.155", "/plan", "Traceback", "OSError",
"ValueError", "Expecting value", "Connection refused"):
assert bad not in msg, (bad, msg)
finally: finally:
lg.removeHandler(h)
restore() restore()