test: update tests for unified SVD label system (Task 7)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""Tests for _build_party_axis_figure and load_party_mp_vectors in explorer.py."""
|
||||
|
||||
import numpy as np
|
||||
import plotly.graph_objects as go
|
||||
import pytest
|
||||
|
||||
|
||||
|
||||
@@ -508,7 +508,7 @@ def _fresh_classifier(monkeypatch):
|
||||
|
||||
|
||||
def test_axis_label_left_right(tmp_path, monkeypatch):
|
||||
"""Positions that closely correlate with left_right scores → label 'Links–Rechts'."""
|
||||
"""Positions that closely correlate with left_right scores → label 'Verzorgingsstaat–Marktwerking'."""
|
||||
_cls = _fresh_classifier(monkeypatch)
|
||||
|
||||
(tmp_path / "party_ideologies.csv").write_text(
|
||||
@@ -537,7 +537,7 @@ def test_axis_label_left_right(tmp_path, monkeypatch):
|
||||
|
||||
result = _cls.classify_axes(positions_by_window, axes, str(tmp_path / "motions.db"))
|
||||
|
||||
assert result["x_label"] == "Links\u2013Rechts"
|
||||
assert result["x_label"] == "Verzorgingsstaat–Marktwerking"
|
||||
assert result["x_quality"]["2022"] >= 0.65
|
||||
|
||||
|
||||
@@ -626,7 +626,7 @@ def test_compute_2d_axes_exposes_global_mean(monkeypatch):
|
||||
|
||||
|
||||
def test_classify_from_titles_left_right():
|
||||
"""Titles dominated by left-right keywords 'LinksRechts'."""
|
||||
"""Titles dominated by left-right keywords -> 'Verzorgingsstaat–Marktwerking'."""
|
||||
from analysis.axis_classifier import _classify_from_titles
|
||||
|
||||
titles = [
|
||||
@@ -637,7 +637,7 @@ def test_classify_from_titles_left_right():
|
||||
"Motie over bijstandsuitkering",
|
||||
]
|
||||
label, confidence = _classify_from_titles(titles)
|
||||
assert label == "Links\u2013Rechts"
|
||||
assert label == "Verzorgingsstaat–Marktwerking"
|
||||
assert confidence >= 0.4
|
||||
|
||||
|
||||
@@ -672,7 +672,7 @@ def test_classify_from_titles_low_confidence():
|
||||
|
||||
|
||||
def test_axis_swap_when_y_is_left_right():
|
||||
"""When y_label is 'Links–Rechts' and x_label is not, positions must be swapped."""
|
||||
"""When y_label is economic left-right and x_label is not, positions must be swapped."""
|
||||
from explorer import _swap_axes
|
||||
|
||||
positions_by_window = {
|
||||
@@ -683,11 +683,11 @@ def test_axis_swap_when_y_is_left_right():
|
||||
}
|
||||
axis_def = {
|
||||
"x_label": "Progressief\u2013Conservatief",
|
||||
"y_label": "Links\u2013Rechts",
|
||||
"y_label": "Verzorgingsstaat–Marktwerking",
|
||||
"x_quality": {"2023": 0.7},
|
||||
"y_quality": {"2023": 0.8},
|
||||
"x_interpretation": {"2023": "prog interpretation"},
|
||||
"y_interpretation": {"2023": "lr interpretation"},
|
||||
"y_interpretation": {"2023": "economic interpretation"},
|
||||
"x_top_motions": {"2023": {"+": [], "-": []}},
|
||||
"y_top_motions": {"2023": {"+": [], "-": []}},
|
||||
"x_label_confidence": {"2023": 0.5},
|
||||
@@ -701,7 +701,7 @@ def test_axis_swap_when_y_is_left_right():
|
||||
assert new_pos["2023"]["PvdA"] == (-0.6, -0.3)
|
||||
|
||||
# Labels swapped
|
||||
assert new_ax["x_label"] == "Links\u2013Rechts"
|
||||
assert new_ax["x_label"] == "Verzorgingsstaat–Marktwerking"
|
||||
assert new_ax["y_label"] == "Progressief\u2013Conservatief"
|
||||
|
||||
# Quality swapped
|
||||
@@ -710,18 +710,18 @@ def test_axis_swap_when_y_is_left_right():
|
||||
|
||||
|
||||
def test_axis_swap_not_applied_when_x_is_left_right():
|
||||
"""When x_label is already 'Links–Rechts', no swap should occur."""
|
||||
"""When x_label is already economic left-right, no swap should occur."""
|
||||
from explorer import _should_swap_axes
|
||||
|
||||
axis_def = {
|
||||
"x_label": "Links\u2013Rechts",
|
||||
"x_label": "Verzorgingsstaat–Marktwerking",
|
||||
"y_label": "Progressief\u2013Conservatief",
|
||||
}
|
||||
assert _should_swap_axes(axis_def) is False
|
||||
|
||||
axis_def2 = {
|
||||
"x_label": "Links\u2013Rechts",
|
||||
"y_label": "Links\u2013Rechts", # both LR — no swap
|
||||
"x_label": "Verzorgingsstaat–Marktwerking",
|
||||
"y_label": "Verzorgingsstaat–Marktwerking", # both economic — no swap
|
||||
}
|
||||
assert _should_swap_axes(axis_def2) is False
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ def test_build_parser_defaults():
|
||||
parser = build_parser()
|
||||
args = parser.parse_args([])
|
||||
assert args.db_path == "data/motions.db"
|
||||
assert args.window_size == "quarterly"
|
||||
assert args.window_size == "annual"
|
||||
assert args.svd_k == 50
|
||||
assert args.dry_run is False
|
||||
|
||||
@@ -72,7 +72,7 @@ def test_run_dry_run(tmp_path, monkeypatch):
|
||||
db_path=db_path,
|
||||
start_date="2024-01-01",
|
||||
end_date="2024-03-31",
|
||||
window_size="quarterly",
|
||||
window_size="annual",
|
||||
svd_k=10,
|
||||
text_model=None,
|
||||
skip_metadata=False,
|
||||
@@ -98,7 +98,7 @@ def test_run_skip_all(tmp_path):
|
||||
db_path=db_path,
|
||||
start_date="2024-01-01",
|
||||
end_date="2024-03-31",
|
||||
window_size="quarterly",
|
||||
window_size="annual",
|
||||
svd_k=10,
|
||||
text_model=None,
|
||||
skip_metadata=True,
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
"""Tests for analysis/svd_labels module."""
|
||||
|
||||
|
||||
def test_get_svd_label_returns_correct_label():
|
||||
"""Test that get_svd_label returns the correct label for each component."""
|
||||
from analysis.svd_labels import get_svd_label
|
||||
|
||||
# Component 1 should return EU-integratie label
|
||||
label1 = get_svd_label(1)
|
||||
assert "EU-integratie" in label1 or "Nationalisme" in label1
|
||||
|
||||
# Component 2 should return Populistisch label
|
||||
label2 = get_svd_label(2)
|
||||
assert "Populistisch" in label2 or "Institutioneel" in label2
|
||||
|
||||
# Component 3 should return Verzorgingsstaat label
|
||||
label3 = get_svd_label(3)
|
||||
assert "Verzorgingsstaat" in label3 or "Marktwerking" in label3
|
||||
|
||||
|
||||
def test_compute_flip_direction_right_on_left():
|
||||
"""Test that flip is True when right parties are on the left."""
|
||||
from analysis.svd_labels import compute_flip_direction
|
||||
|
||||
# Right parties have negative scores (on left), left parties have positive
|
||||
party_scores = {
|
||||
"VVD": [-0.5, 0.0], # Right party, component 1 score = -0.5
|
||||
"PVV": [-0.8, 0.0], # Right party
|
||||
"SP": [0.6, 0.0], # Left party, component 1 score = 0.6
|
||||
"DENK": [0.4, 0.0], # Left party
|
||||
}
|
||||
|
||||
# Component 1: right_mean = -0.65, left_mean = 0.5
|
||||
# right_mean < left_mean, so flip = True
|
||||
assert compute_flip_direction(1, party_scores) is True
|
||||
|
||||
|
||||
def test_compute_flip_direction_right_on_right():
|
||||
"""Test that flip is False when right parties are already on the right."""
|
||||
from analysis.svd_labels import compute_flip_direction
|
||||
|
||||
# Right parties have positive scores (on right), left parties have negative
|
||||
party_scores = {
|
||||
"VVD": [0.5, 0.0], # Right party, component 1 score = 0.5
|
||||
"PVV": [0.8, 0.0], # Right party
|
||||
"SP": [-0.6, 0.0], # Left party
|
||||
"DENK": [-0.4, 0.0], # Left party
|
||||
}
|
||||
|
||||
# Component 1: right_mean = 0.65, left_mean = -0.5
|
||||
# right_mean > left_mean, so flip = False
|
||||
assert compute_flip_direction(1, party_scores) is False
|
||||
|
||||
|
||||
def test_compute_flip_direction_insufficient_data():
|
||||
"""Test that flip is False when there's insufficient data."""
|
||||
from analysis.svd_labels import compute_flip_direction
|
||||
|
||||
# No right parties in data
|
||||
party_scores = {
|
||||
"SP": [0.6, 0.0],
|
||||
"DENK": [0.4, 0.0],
|
||||
}
|
||||
|
||||
assert compute_flip_direction(1, party_scores) is False
|
||||
|
||||
# No left parties in data
|
||||
party_scores = {
|
||||
"VVD": [0.5, 0.0],
|
||||
"PVV": [0.8, 0.0],
|
||||
}
|
||||
|
||||
assert compute_flip_direction(1, party_scores) is False
|
||||
Reference in New Issue
Block a user