88 个测试覆盖配置继承、注册表、GPU 守卫、YOLO 格式解析、数据集、模型形状、 标签模式、聚类原语与 SimCLR 损失,以及 train.py / eval.py / 聚类脚本的入口接线。 含两条回归测试: - PCA 白化放大噪声方向导致簇塌陷(默认 whiten=False 的依据) - classes 写成 data.yaml 路径时 num_classes 必须是类别数而非路径字符串长度 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
"""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
|