test_db_upgrade.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. """db_upgrade 纯逻辑测试(不连接任何数据库)。"""
  2. from alembic.config import Config
  3. from alembic.script import ScriptDirectory
  4. from dms.db_upgrade import _mask_password, resolve_migrations_dir, run_upgrade
  5. def _script() -> ScriptDirectory:
  6. cfg = Config()
  7. cfg.set_main_option("script_location", str(resolve_migrations_dir()))
  8. return ScriptDirectory.from_config(cfg)
  9. def test_resolve_migrations_dir_contains_env_and_versions():
  10. migrations = resolve_migrations_dir()
  11. assert (migrations / "env.py").exists()
  12. assert (migrations / "versions").is_dir()
  13. def test_migration_chain_head_and_steps_from_0013():
  14. """远端生产库 0013 → head 恰好经过 0014、0015,且两者 upgrade 不含数据删除。"""
  15. script = _script()
  16. assert script.get_current_head() == "0015_login_ip_restriction"
  17. steps = [
  18. r.revision
  19. for r in reversed(
  20. list(script.walk_revisions("0013_document_password_lock", "head"))
  21. )
  22. ]
  23. assert steps == [
  24. "0013_document_password_lock",
  25. "0014_document_relations",
  26. "0015_login_ip_restriction",
  27. ]
  28. def test_run_upgrade_lists_pending_steps_excluding_current(monkeypatch, capsys):
  29. """0013 升级到 head:待执行清单只含 0014/0015,当前版本不重复出现。"""
  30. monkeypatch.setenv("DMS_DATABASE_URL", "mysql+pymysql://u:secret@127.0.0.1:3306/dms")
  31. versions = iter(["0013_document_password_lock", "0015_login_ip_restriction"])
  32. monkeypatch.setattr(
  33. "dms.db_upgrade._read_current_version", lambda url: next(versions)
  34. )
  35. monkeypatch.setattr("alembic.command.upgrade", lambda cfg, rev: None)
  36. assert run_upgrade(assume_yes=True) == 0
  37. out = capsys.readouterr().out
  38. assert " - 0014_document_relations" in out
  39. assert " - 0015_login_ip_restriction" in out
  40. assert " - 0013" not in out
  41. assert "secret" not in out # 输出中的地址必须已脱敏
  42. def test_mask_password():
  43. url = "mysql+pymysql://dms_app:asdqwe123!@82.156.83.248:3306/dms?charset=utf8mb4"
  44. assert (
  45. _mask_password(url)
  46. == "mysql+pymysql://dms_app:***@82.156.83.248:3306/dms?charset=utf8mb4"
  47. )
  48. assert _mask_password("sqlite:///foo.db") == "sqlite:///foo.db"
  49. def test_run_upgrade_requires_database_url(monkeypatch, capsys):
  50. """未配置 DMS_DATABASE_URL 时拒绝执行(fail-fast,绝不 fallback 到 ini 地址)。"""
  51. monkeypatch.delenv("DMS_DATABASE_URL", raising=False)
  52. assert run_upgrade(assume_yes=True) == 2
  53. assert "DMS_DATABASE_URL" in capsys.readouterr().out