test_db_live.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. """live 门禁测试 — 触真实远程 MySQL, 无网络/库不可达时整组 skip。
  2. run: pytest tests/test_db_live.py -v
  3. """
  4. from __future__ import annotations
  5. import pytest
  6. pymysql = pytest.importorskip("pymysql")
  7. from pbot.db.stores import ( # noqa: E402
  8. AccountStore,
  9. RoleStore,
  10. RunLogStore,
  11. ServerStore,
  12. ZoneStore,
  13. init_all,
  14. )
  15. @pytest.fixture(scope="module")
  16. def conn() -> object:
  17. try:
  18. from pbot.db.engine import get_connection
  19. real = get_connection()
  20. except Exception as e: # noqa: BLE001
  21. pytest.skip(f"远程 MySQL 不可达: {e}")
  22. yield real
  23. real.close()
  24. def test_init_tables(conn: object) -> None:
  25. n = init_all(conn) # type: ignore[arg-type]
  26. assert n == 11
  27. with conn.cursor() as cur: # type: ignore[attr-defined]
  28. cur.execute("SHOW TABLES LIKE 'pb_%'")
  29. tables = {r["Tables_in_996cq (pb_%)"] for r in cur.fetchall()}
  30. assert len(tables) == 11
  31. def test_seed_data(conn: object) -> None:
  32. servers = ServerStore(conn) # type: ignore[arg-type]
  33. server = servers.get_by_name("玖扬复古176")
  34. assert server is not None
  35. accounts = AccountStore(conn).list_for_server(int(server["id"])) # type: ignore[arg-type]
  36. assert len(accounts) == 3
  37. tasks = servers.tasks_with_scripts(int(server["id"]))
  38. assert len(tasks) == 10
  39. seqs = [int(t["seq"]) for t in tasks]
  40. assert seqs == sorted(seqs)
  41. def test_zone_latest(conn: object) -> None:
  42. zone = ZoneStore(conn).latest_enabled() # type: ignore[arg-type]
  43. assert zone is None or int(zone["state"]) == 1
  44. def test_role_crud_roundtrip(conn: object) -> None: # type: ignore[arg-type]
  45. """角色 upsert + 清理(临时数据)。"""
  46. servers = ServerStore(conn)
  47. server = servers.get_by_name("玖扬复古176")
  48. assert server is not None
  49. with conn.cursor() as cur:
  50. cur.execute(
  51. "SELECT id FROM pb_zone WHERE server_id=%s "
  52. "ORDER BY open_time DESC LIMIT 1", (server["id"],))
  53. zone = cur.fetchone()
  54. if zone is None:
  55. pytest.skip("pb_zone 无数据(未扫描)")
  56. roles = RoleStore(conn)
  57. from datetime import datetime
  58. acct = AccountStore(conn).list_for_server(int(server["id"]))[0]
  59. row = roles.ensure_for_zone(
  60. account_id=int(acct["id"]), server_id=int(server["id"]),
  61. zone_id=int(zone["id"]), server_name="t", zone_name="t",
  62. spawn_at=datetime.now()) # noqa: DTZ005 - 库侧 naive 定案
  63. rid = int(row["id"])
  64. roles.set_role_name(rid, "测试角色")
  65. roles.set_progress(rid, 3, 10)
  66. got = roles.get(rid)
  67. assert got is not None
  68. assert got["role_name"] == "测试角色"
  69. assert int(got["progress_done"]) == 3
  70. with conn.cursor() as cur:
  71. cur.execute("DELETE FROM pb_role WHERE id=%s", (rid,))
  72. cur.execute(
  73. "DELETE FROM pb_role_task_progress WHERE role_id=%s", (rid,))
  74. def test_runlog_roundtrip(conn: object) -> None: # type: ignore[arg-type]
  75. servers = ServerStore(conn)
  76. server = servers.get_by_name("玖扬复古176")
  77. assert server is not None
  78. roles = RoleStore(conn)
  79. existing = roles.list_with_names()
  80. if not existing:
  81. pytest.skip("无角色行(未分配)")
  82. rid = int(existing[0]["id"])
  83. runs = RunLogStore(conn)
  84. run_id = runs.start(rid, "manual")
  85. runs.set_pid(run_id, 999999)
  86. runs.finish(run_id, 0, "test")
  87. with conn.cursor() as cur:
  88. cur.execute("DELETE FROM pb_run_log WHERE id=%s", (run_id,))