发布计划不再绑设备、不再依赖账号台账:上传文件名 `名字_日期_编号`(标题行 `标题 || 正文_名字_日期_编号`),运行时读本机当前抖音昵称取计划;靠循环块 「一轮把本机待发的号跑完」自动切号,一直发到发完。 · 解析/配对换键:右锚定认名字(不许含下划线、不许纯数字 —— 不合法直接拒收并说清原因), 删掉三处"手机号必须命中台账"的校验,加索引 ix_video_plan_name_date(启动时补建) · 新步骤三个:读本机账号名字 / 切换账号(**按名字点控件**、切完回读校验、遇登录页停本设备)/ 循环本机待发的号(试过不回头、跑一轮没进展就换号、停止·超时·上限三个干净出口) · 发布骨架改 18 步:读名字 → 校验账号(cmp_source=account_target)→ 推送(**推送前重读昵称核对**) → 抖音流程 → 标记结果;push_release 的 account 默认 name · 账号管理整页下线:删 core/ledger.py(serial_of 迁到 core/device_pool.py)、6 个 /api/ledger*、 「账号」页与 ledger.js、设备池「账号」列、设备端账号块;发布计划升为一级页签; device_account 表与 42 行历史数据保留、仍在备份清单内(**停用不等于删数据**) · 人工入口「按名字找设备」:新增 core/account_probe.py(只读探测、跳过在跑任务的设备) + POST /api/video_plan/push_by_account,没设备登着的号逐条报出来; 推送时把"实际是谁发的"写进 posted_serial / posted_device_name · 通知:新增 task.account.switch_failed / task.account.need_login · schema v12(posted_*)/ v13(device.cur_account_name / cur_name_at) · 文档同步:TASK_DEV / API / DATA_MODEL / ARCHITECTURE / NOTIFY / DEVICE_AGENT / DEPLOY / DEVELOPMENT / README / .env.example(两个抖音控件选择器抓一次填 .env) · 新增 scripts/tests/:6 套用例 + run_all.py(临时库 + 假设备,不碰真实数据、不连真机)
47 lines
2.0 KiB
Python
47 lines
2.0 KiB
Python
"""发布计划「按名字发」相关用例:一次跑完,汇总结果。
|
||
|
||
用法(项目根目录):
|
||
.venv/Scripts/python scripts/tests/run_all.py # Windows
|
||
.venv/bin/python scripts/tests/run_all.py # Linux/macOS
|
||
|
||
这些用例的**铁律**(与 doc/DEVELOPMENT.md 的测试约定一致):
|
||
· 一律**临时 SQLite + 临时目录**(`DATABASE_URL` / `DATA_VIDEO_DIR` 指向 tempfile 建的目录),
|
||
**绝不碰用户的真实库与真实素材目录**;
|
||
· 需要设备的地方一律用**假设备**(桩对象/stub),**不连真机、不下发 adb**;
|
||
· 每个用例自己退出码非 0 表示失败,本脚本据此汇总。
|
||
|
||
覆盖:
|
||
test_parse_name 文件名/标题行解析(`名字_日期_编号`、`标题 || 正文_...`、各种拒收)
|
||
test_upload_name 上传 + 配标题落库(不再依赖任何账号台账)
|
||
test_name_scope 读本机账号名字、按名字取计划、推送前核对
|
||
test_switch_account 切换账号(按名字点控件、回读校验、登录页停设备)
|
||
test_foreach_account 循环本机待发的号(一轮跑完、试过不回头、干净退出)
|
||
test_push_by_name 按名字找设备推送(matched/unmatched、缓存)
|
||
"""
|
||
import os
|
||
import subprocess
|
||
import sys
|
||
|
||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||
CASES = ["test_parse_name.py", "test_upload_name.py", "test_name_scope.py",
|
||
"test_switch_account.py", "test_foreach_account.py", "test_push_by_name.py"]
|
||
|
||
if hasattr(sys.stdout, "reconfigure"):
|
||
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
||
|
||
failed = []
|
||
for name in CASES:
|
||
print("=" * 66)
|
||
print("▶", name)
|
||
print("=" * 66)
|
||
r = subprocess.run([sys.executable, os.path.join(HERE, name)])
|
||
if r.returncode != 0:
|
||
failed.append(name)
|
||
|
||
print()
|
||
print("=" * 66)
|
||
if failed:
|
||
print("❌ 失败 %d / %d:%s" % (len(failed), len(CASES), "、".join(failed)))
|
||
sys.exit(1)
|
||
print("✅ 全部 %d 个用例通过" % len(CASES))
|