test_store.py 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. """SQLite 数据层离线测:写入幂等 + 拍平 + 分页筛选(临时库,不碰 data/app.db)。"""
  2. from __future__ import annotations
  3. from acquisition import store
  4. def _db(tmp_path):
  5. return store.connect(tmp_path / "t.db")
  6. def test_insert_queries_idempotent_and_axes(tmp_path):
  7. c = _db(tmp_path)
  8. items = [{"query": "q1", "实质": "军人", "阶段": "灵感"}, {"query": "q2", "形式": "排比"}]
  9. assert store.insert_queries(c, "r1", "多轴", items, ts=100) == 2
  10. # 重导同 (run,method) → 覆盖不叠加
  11. assert store.insert_queries(c, "r1", "多轴", items, ts=100) == 2
  12. res = store.list_queries(c, method="多轴")
  13. assert res["total"] == 2
  14. assert res["items"][0]["axes"] == {"实质": "军人", "阶段": "灵感"} # query 不进 axes
  15. assert "query" not in res["items"][0]["axes"]
  16. def test_insert_queries_skips_empty_query(tmp_path):
  17. c = _db(tmp_path)
  18. n = store.insert_queries(c, "r1", "m", [{"query": ""}, {"实质": "x"}, {"query": "ok"}], ts=1)
  19. assert n == 1
  20. def test_search_flatten_topk_and_ok(tmp_path):
  21. c = _db(tmp_path)
  22. recs = [
  23. {"method": "M", "query": "q1",
  24. "douyin": {"ok": [{"title": "t", "url": "u", "cover": "/c.jpg", "video": "/v.mp4"},
  25. {"title": "t2", "url": "u2", "cover": "/c2.jpg", "video": "/v2.mp4"}],
  26. "error": None},
  27. "weixin": {"ok": [{"title": "w", "url": "wu", "cover": "/wc.jpg", "nick": "号"}], "error": None}},
  28. {"method": "M", "query": "q2",
  29. "douyin": {"ok": [], "error": "未搜到"},
  30. "weixin": {"ok": [], "error": "搜索失败: x"}},
  31. ]
  32. # q1: 2 抖音 + 1 微信 = 3 个 ok 行;q2: 抖音空 + 微信空 = 2 个 ok=0 行 → 共 5
  33. assert store.insert_search_results(c, "s1", recs, ts=5) == 5
  34. ok_dy = store.list_search(c, platform="douyin", ok=True)
  35. assert ok_dy["total"] == 2 # q1 的两个视频
  36. assert {i["video"] for i in ok_dy["items"]} == {"/v.mp4", "/v2.mp4"}
  37. # 搜过但无结果 → ok=0 行带 error(按 query 取得到,按钮才显示「搜过·无结果」)
  38. bad = store.list_search(c, platform="weixin", ok=False)
  39. assert bad["total"] == 1 and "失败" in bad["items"][0]["extra"]["error"]
  40. good_wx = store.list_search(c, platform="weixin", ok=True)
  41. assert good_wx["items"][0]["extra"]["nick"] == "号"
  42. # summary:q1 有 3 个结果,q2 有 0 个但被记为搜过(total=2 行)
  43. s = store.search_summary(c)
  44. assert s["q1"]["ok"] == 3 and s["q2"]["ok"] == 0 and s["q2"]["total"] == 2
  45. def test_pagination(tmp_path):
  46. c = _db(tmp_path)
  47. store.insert_queries(c, "r", "m", [{"query": f"q{i}"} for i in range(25)], ts=1)
  48. p1 = store.list_queries(c, page=1, size=10)
  49. p3 = store.list_queries(c, page=3, size=10)
  50. assert p1["total"] == 25 and len(p1["items"]) == 10
  51. assert len(p3["items"]) == 5 # 余 5 条
  52. assert p1["items"][0]["query"] != p3["items"][0]["query"]
  53. def test_runs_and_methods(tmp_path):
  54. c = _db(tmp_path)
  55. store.insert_queries(c, "rq", "方法A", [{"query": "a"}], ts=2)
  56. store.insert_search_results(c, "rs", [{"method": "方法B", "query": "b",
  57. "douyin": None, "weixin": None}], ts=3)
  58. runs = {r["run_id"]: r["kind"] for r in store.list_runs(c)}
  59. assert runs == {"rq": "queries", "rs": "search"}
  60. assert store.list_methods(c, "queries") == ["方法A"]
  61. assert store.list_methods(c, "search_results") == ["方法B"]