tests/weights: 16 tests for WeightSet defaults + from_dict adapter

arborist/substrate/weights.py was zero-coverage. 73 LOC of
dataclass + adapter. Tests pin:

  - documented defaults from the module docstring (each weight
    has a comment block explaining its design intent; tests
    pin the values so a PR that flips alpha=1.0 → 0.5 fires the
    test and forces an explicit docstring update)
  - documented invariants: alpha=beta=gamma (3 batteries equal),
    eta > alpha (regression heavier than improvement),
    reserved-zero defaults (zeta/iota/kappa)
  - as_dict() returns all 11 fields; lambda_ key (not "lambda" —
    keyword)
  - from_dict() greek-letter keys, "lambda" → "lambda_" translation
    (JSON/YAML friendly), missing-keys-default fall-through,
    extra-keys silent drop, str → float coercion, int → float
    coercion
  - frozen-dataclass invariant (mutation raises FrozenInstanceError)
  - dataclass equality

Full suite: 1881 passed, 54 skipped. tests/ count growing
roughly 1655 → 1881 (+226) across today's autonomous quality
session.
This commit is contained in:
russell@unturf.com 2026-05-10 12:41:49 -04:00
parent 3d0f02e1ac
commit 3ef8975623
No known key found for this signature in database

180
tests/test_weights.py Normal file
View file

@ -0,0 +1,180 @@
"""Tests for ``arborist.substrate.weights`` — WeightSet defaults +
``from_dict`` adapter (#000012 Phase 1a).
Pure-stdlib dataclass + classmethod-style adapter; small surface.
This pins:
- documented defaults (lifted from the module docstring)
- greek-letter and Python-safe key aliases ("lambda" ↔ "lambda_")
- missing-keys fall-through to defaults
- extra-keys silently ignored
- string values coerce to float
- frozen-dataclass invariant (mutation raises)
"""
from __future__ import annotations
import dataclasses
import pytest
from arborist.substrate.weights import (
DEFAULT_WEIGHTS,
WeightSet,
from_dict,
)
# --- defaults pinned to the docstring ------------------------------
def test_default_weights_match_documented_values():
"""Each weight in the dataclass docstring is pinned. If a future
PR changes a default, this test fires and forces an explicit
update of both the docstring AND the test."""
assert DEFAULT_WEIGHTS.alpha == 1.0
assert DEFAULT_WEIGHTS.beta == 1.0
assert DEFAULT_WEIGHTS.gamma == 1.0
assert DEFAULT_WEIGHTS.delta == 0.5
assert DEFAULT_WEIGHTS.epsilon == 0.3
assert DEFAULT_WEIGHTS.zeta == 0.0 # validator-diversity off in single-validator
assert DEFAULT_WEIGHTS.eta == 2.0 # regression > improvement weight
assert DEFAULT_WEIGHTS.theta == 0.5
assert DEFAULT_WEIGHTS.iota == 0.0 # reserved
assert DEFAULT_WEIGHTS.kappa == 0.0 # reserved
assert DEFAULT_WEIGHTS.lambda_ == 0.5
def test_eta_is_heavier_than_alpha():
"""Documented invariant from the docstring:
'η (RegressionPenalty) heavier than improvement weights so the
scorer is biased toward refusing regressions.'"""
assert DEFAULT_WEIGHTS.eta > DEFAULT_WEIGHTS.alpha
assert DEFAULT_WEIGHTS.eta > DEFAULT_WEIGHTS.beta
assert DEFAULT_WEIGHTS.eta > DEFAULT_WEIGHTS.gamma
def test_three_batteries_equal_by_default():
"""Documented invariant: 'α = β = γ (3 batteries weighted equally
by default).'"""
assert DEFAULT_WEIGHTS.alpha == DEFAULT_WEIGHTS.beta == DEFAULT_WEIGHTS.gamma
def test_reserved_weights_are_zero_phase_1a():
"""Phase 1a discipline: validator-diversity / security / complexity
are zero by default. v8 multi-validator deployments must opt in."""
assert DEFAULT_WEIGHTS.zeta == 0.0
assert DEFAULT_WEIGHTS.iota == 0.0
assert DEFAULT_WEIGHTS.kappa == 0.0
# --- as_dict --------------------------------------------------------
def test_as_dict_returns_all_eleven_fields():
d = DEFAULT_WEIGHTS.as_dict()
expected_keys = {
"alpha", "beta", "gamma", "delta", "epsilon", "zeta",
"eta", "theta", "iota", "kappa", "lambda_",
}
assert set(d.keys()) == expected_keys
def test_as_dict_uses_lambda_underscore_key():
"""``lambda`` is a Python keyword → dataclass uses ``lambda_``;
as_dict() carries it forward unchanged. Callers serializing to
JSON / YAML rename to bare ``lambda`` if needed."""
d = DEFAULT_WEIGHTS.as_dict()
assert "lambda_" in d
assert "lambda" not in d
# --- from_dict adapter ---------------------------------------------
def test_from_dict_uses_greek_letter_keys():
ws = from_dict({"alpha": 0.7, "beta": 0.8, "gamma": 0.9})
assert ws.alpha == 0.7
assert ws.beta == 0.8
assert ws.gamma == 0.9
# Unspecified keys fall through to defaults.
assert ws.delta == DEFAULT_WEIGHTS.delta
def test_from_dict_translates_lambda_to_lambda_underscore():
"""JSON/YAML configs use bare ``lambda`` (the Greek letter, not
the keyword). from_dict translates to the Python-safe field
name ``lambda_``."""
ws = from_dict({"lambda": 0.99})
assert ws.lambda_ == 0.99
# Bare 'lambda' did not survive into a hidden field.
assert "lambda" not in ws.as_dict()
def test_from_dict_lambda_underscore_key_also_accepted():
"""For Python callers writing config dicts directly, ``lambda_``
is the natural key name; from_dict accepts it too."""
ws = from_dict({"lambda_": 0.42})
assert ws.lambda_ == 0.42
def test_from_dict_missing_keys_fall_through_to_defaults():
"""Empty dict → identical to DEFAULT_WEIGHTS."""
ws = from_dict({})
assert ws == DEFAULT_WEIGHTS
def test_from_dict_partial_override_preserves_other_defaults():
ws = from_dict({"alpha": 0.5})
assert ws.alpha == 0.5
# Every other field is unchanged.
assert ws.beta == DEFAULT_WEIGHTS.beta
assert ws.eta == DEFAULT_WEIGHTS.eta
assert ws.lambda_ == DEFAULT_WEIGHTS.lambda_
def test_from_dict_ignores_unknown_keys():
"""Defensive: extra keys (e.g. "mu" — never defined) are
silently dropped rather than raising. Forward-compat with
config files that include vendor-specific tags."""
ws = from_dict({"alpha": 0.6, "mu": 1.234, "extra_metadata": "ignore"})
assert ws.alpha == 0.6
# mu / extra_metadata silently dropped.
assert not hasattr(ws, "mu")
def test_from_dict_coerces_string_to_float():
"""JSON/YAML may pass numeric weights as strings. from_dict
coerces via float()."""
ws = from_dict({"alpha": "0.7", "lambda": "0.3"})
assert ws.alpha == 0.7
assert ws.lambda_ == 0.3
def test_from_dict_int_input_becomes_float():
ws = from_dict({"alpha": 1})
assert ws.alpha == 1.0
assert isinstance(ws.alpha, float)
# --- frozen invariant ----------------------------------------------
def test_weight_set_is_frozen():
"""WeightSet is dataclass(frozen=True) — mutation raises
FrozenInstanceError. Pinned so a future @dataclass change
forces this test to be updated explicitly."""
with pytest.raises(dataclasses.FrozenInstanceError):
DEFAULT_WEIGHTS.alpha = 99.0
def test_weight_sets_equal_by_value():
"""Two WeightSet instances with identical fields compare equal —
standard dataclass equality. Used by tests + audit-trail
serialization."""
a = WeightSet(alpha=0.5, beta=0.6)
b = WeightSet(alpha=0.5, beta=0.6)
assert a == b
# Different values → not equal.
c = WeightSet(alpha=0.5, beta=0.7)
assert a != c