"""SwanLab 可视化封装:可用时记录,不可用时必须静默降级、不影响训练。""" import builtins import pytest from engine.visualizer import SwanLabLogger def test_disabled_logger_is_noop(tmp_path): logger = SwanLabLogger(enabled=False, work_dir=tmp_path) assert logger.enabled is False logger.log({"loss": 1.0}, step=1) logger.finish() def test_mode_disabled_is_treated_as_off(tmp_path): assert SwanLabLogger(work_dir=tmp_path, mode="disabled").enabled is False def test_invalid_mode_raises(tmp_path): with pytest.raises(ValueError, match="swanlab mode"): SwanLabLogger(work_dir=tmp_path, mode="cloud") def test_missing_swanlab_degrades_gracefully(tmp_path, monkeypatch): real_import = builtins.__import__ def fake_import(name, *args, **kwargs): if name == "swanlab": raise ImportError("no swanlab") return real_import(name, *args, **kwargs) monkeypatch.setattr(builtins, "__import__", fake_import) logger = SwanLabLogger(work_dir=tmp_path) assert logger.enabled is False logger.log({"loss": 1.0}) # 不应抛异常 def test_offline_run_records_metrics(tmp_path): pytest.importorskip("swanlab") logger = SwanLabLogger( work_dir=tmp_path, project="mte-tests", mode="offline", config={"lr": 0.1} ) if not logger.enabled: # 环境不允许起 run 时跳过,不让测试变脆 pytest.skip("swanlab 无法在当前环境初始化") logger.log({"total": 1.0, "lr": 0.1}, step=1, prefix="train/") logger.finish() assert (tmp_path / "swanlog").exists() def test_log_failure_disables_instead_of_raising(tmp_path): logger = SwanLabLogger(enabled=False, work_dir=tmp_path) logger.enabled = True # 伪造已启用但底层不可用的状态 class Broken: @staticmethod def log(*args, **kwargs): raise RuntimeError("network down") logger._swanlab = Broken() logger.log({"loss": 1.0}, step=1) assert logger.enabled is False