feat(m1): attribute vocab + sampling (T1.2)
- ATTRIBUTE_VOCAB (16 AIOps channels w/ units) - FREQ_BANDS (6 sampling resolutions) - sample_attributes(n_channels, seed) -> unique-name, reproducible - tests/test_attributes.py (8 tests, RED->GREEN) Exit criteria: fields complete, count correct, seed-reproducible.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
"""Tests for attribute vocab + sampling (T1.2)."""
|
||||
import numpy as np
|
||||
|
||||
from tsmm.data.attributes import sample_attributes, ATTRIBUTE_VOCAB, FREQ_BANDS
|
||||
|
||||
|
||||
# ─── field completeness ────────────────────────────────────────────────────
|
||||
def test_each_sampled_attribute_has_required_fields():
|
||||
attrs = sample_attributes(n_channels=4, seed=0)
|
||||
assert len(attrs) == 4
|
||||
for a in attrs:
|
||||
assert set(a.keys()) >= {"name", "unit", "freq"}
|
||||
assert isinstance(a["name"], str) and a["name"]
|
||||
assert isinstance(a["unit"], str) and a["unit"]
|
||||
assert isinstance(a["freq"], str) and a["freq"]
|
||||
|
||||
|
||||
def test_names_are_unique_within_a_sample():
|
||||
attrs = sample_attributes(n_channels=5, seed=1)
|
||||
names = [a["name"] for a in attrs]
|
||||
assert len(names) == len(set(names)), "channel names must be unique"
|
||||
|
||||
|
||||
# ─── correctness of count ──────────────────────────────────────────────────
|
||||
def test_count_matches_request():
|
||||
for n in (1, 2, 8):
|
||||
assert len(sample_attributes(n_channels=n, seed=0)) == n
|
||||
|
||||
|
||||
def test_raises_when_request_exceeds_vocab():
|
||||
# vocab is finite; requesting more channels than distinct names must raise.
|
||||
import pytest
|
||||
|
||||
too_many = len(ATTRIBUTE_VOCAB) + 1
|
||||
with pytest.raises(ValueError):
|
||||
sample_attributes(n_channels=too_many, seed=0)
|
||||
|
||||
|
||||
# ─── reproducibility ───────────────────────────────────────────────────────
|
||||
def test_same_seed_gives_same_result():
|
||||
a = sample_attributes(n_channels=6, seed=42)
|
||||
b = sample_attributes(n_channels=6, seed=42)
|
||||
assert a == b
|
||||
|
||||
|
||||
def test_different_seed_gives_different_result():
|
||||
a = sample_attributes(n_channels=6, seed=1)
|
||||
b = sample_attributes(n_channels=6, seed=2)
|
||||
assert a != b
|
||||
|
||||
|
||||
# ─── vocab sanity ──────────────────────────────────────────────────────────
|
||||
def test_attribute_vocab_is_non_empty():
|
||||
assert len(ATTRIBUTE_VOCAB) >= 6 # CPU/mem/traffic/latency/temp/rps ...
|
||||
for entry in ATTRIBUTE_VOCAB:
|
||||
assert "name" in entry and "unit" in entry
|
||||
|
||||
|
||||
def test_freq_bands_are_documented():
|
||||
assert len(FREQ_BANDS) >= 2
|
||||
for band in FREQ_BANDS:
|
||||
assert isinstance(band, str) and band # e.g. "1s", "10s", "1min"
|
||||
Reference in New Issue
Block a user