"""data 包测试。""" from __future__ import annotations import numpy as np import pytest pytestmark = pytest.mark.skip(reason="未实现:见 docs/03-roadmap.md L0/L1") def test_detect_outliers_finds_planted_points(): """人工埋 3 个离群点,IQR 法应正好命中 3 个。""" from mcm_toolkit.data import detect_outliers x = np.concatenate([np.arange(100.0), [1e6, -1e6, 1e7]]) mask = np.asarray(detect_outliers(x, method="iqr")) assert mask.sum() == 3 assert mask[-3:].all() def test_detect_outliers_returns_mask_not_filtered_data(): """约定:只标不删——返回与原数据同形的布尔掩码。""" from mcm_toolkit.data import detect_outliers x = np.arange(50.0) mask = np.asarray(detect_outliers(x, method="zscore")) assert mask.shape == x.shape assert mask.dtype == bool def test_normalize_minmax_range(rng): from mcm_toolkit.data import normalize x = rng.normal(size=(50, 3)) out = np.asarray(normalize(x, method="minmax")) assert np.allclose(out.min(axis=0), 0.0) assert np.allclose(out.max(axis=0), 1.0) def test_standardize_has_zero_mean_unit_std(rng): from mcm_toolkit.data import standardize x = rng.normal(5, 3, size=1000) out = np.asarray(standardize(x)) assert abs(out.mean()) < 1e-9 assert abs(out.std() - 1.0) < 1e-9 def test_train_test_split_sizes_and_no_overlap(rng): from mcm_toolkit.data import train_test_split X = rng.normal(size=(100, 2)) Xtr, Xte = train_test_split(X, test_size=0.2, random_state=0) assert len(Xtr) == 80 and len(Xte) == 20 assert len({tuple(r) for r in Xtr} & {tuple(r) for r in Xte}) == 0 def test_load_table_detects_gbk(tmp_path): """国内赛题数据常见 GBK,编码探测必须能兜住。""" from mcm_toolkit.data import load_table p = tmp_path / "gbk.csv" p.write_bytes("城市,人口\n北京,2189\n".encode("gbk")) df = load_table(p) assert list(df.columns) == ["城市", "人口"]