feat: add standard init-db CLI for host install schema ensure
All checks were successful
技能自动化发布 / release (push) Successful in 4s
All checks were successful
技能自动化发布 / release (push) Successful in 4s
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
|
||||
| 场景 | 放在哪里 | 默认是否运行 | 说明 |
|
||||
|------|----------|--------------|------|
|
||||
| CLI / health / version / metadata / runtime 路径 | `tests/test_*.py` | 是 | 默认必跑,保持轻量、无外联 |
|
||||
| CLI / health / version / init-db / metadata / runtime 路径 | `tests/test_*.py` | 是 | 默认必跑,保持轻量、无外联 |
|
||||
| 纯函数 / 业务规则 | `tests/test_*.py` | 是 | 不依赖真实外部系统 |
|
||||
| service 层契约 | 从 `tests/samples/test_service_contract.py.sample` 复制到 `tests/test_service_contract.py` | 是,复制后 | 用 `FakeAdapter` / stub 注入外部依赖 |
|
||||
| 外源同步契约 | 从 `tests/samples/test_sync_contract.py.sample` 复制 | 是,复制后 | 幂等 / 事务 / 空结果保护 / 不导出文件 |
|
||||
@@ -35,6 +35,7 @@
|
||||
- [ ] `python tests/run_tests.py -v` 能通过(含 platform-kit 导入与无 vendored core 守护)。
|
||||
- [ ] `python scripts/main.py health` 能通过(输出 runtime diagnostics;warning 不导致非零退出)。
|
||||
- [ ] `python scripts/main.py version` 输出 JSON,且 `skill` 与目录名 / `SKILL.md` / `constants.SKILL_SLUG` 一致。
|
||||
- [ ] `python scripts/main.py init-db` 幂等创建本地库并输出 JSON(`ok` / `skill` / `db_path`)。
|
||||
- [ ] 所有 DB / 文件写入都在 `IsolatedDataRoot`(或等价隔离)下测试,不写真实数据目录。
|
||||
- [ ] 外部系统默认使用 mock / `FakeAdapter`,不访问真实 API,不打开真实 RPA。
|
||||
- [ ] 至少有 1 个成功路径测试。
|
||||
|
||||
@@ -27,6 +27,7 @@ class TestCliSmoke(unittest.TestCase):
|
||||
out = buf.getvalue()
|
||||
self.assertIn("通用业务技能模板", out)
|
||||
self.assertIn("health", out)
|
||||
self.assertIn("init-db", out)
|
||||
|
||||
def test_health_zero(self) -> None:
|
||||
old_record = os.environ.get("OPENCLAW_RECORD_VIDEO")
|
||||
@@ -57,6 +58,26 @@ class TestCliSmoke(unittest.TestCase):
|
||||
self.assertIn("skill", payload)
|
||||
self.assertEqual(payload["skill"], SKILL_SLUG)
|
||||
|
||||
def test_init_db_creates_database_and_is_idempotent(self) -> None:
|
||||
with IsolatedDataRoot(user_id="_cli_init_db"):
|
||||
config.reset_cache()
|
||||
buf = io.StringIO()
|
||||
with redirect_stdout(buf), redirect_stderr(io.StringIO()):
|
||||
rc = main(["init-db"])
|
||||
self.assertEqual(rc, 0)
|
||||
payload = json.loads(buf.getvalue().strip())
|
||||
self.assertTrue(payload["ok"])
|
||||
self.assertEqual(payload["skill"], SKILL_SLUG)
|
||||
self.assertTrue(os.path.isfile(payload["db_path"]))
|
||||
|
||||
buf2 = io.StringIO()
|
||||
with redirect_stdout(buf2), redirect_stderr(io.StringIO()):
|
||||
rc2 = main(["init-db"])
|
||||
self.assertEqual(rc2, 0)
|
||||
payload2 = json.loads(buf2.getvalue().strip())
|
||||
self.assertTrue(payload2["ok"])
|
||||
self.assertEqual(payload2["db_path"], payload["db_path"])
|
||||
|
||||
def test_logs_empty_returns_zero(self) -> None:
|
||||
with IsolatedDataRoot():
|
||||
buf = io.StringIO()
|
||||
|
||||
Reference in New Issue
Block a user