| from __future__ import annotations |
| import yaml |
|
|
|
|
| def test_assemble_spec_yaml_creates_valid_yaml(tmp_path): |
| from core.spec import assemble_spec_yaml |
|
|
| route = {"sectors": ["WASH", "Food Security"], "lens": [], "type": []} |
| bind_results = { |
| "rcsi": { |
| "indicator_id": "rcsi", |
| "variables": ["cope_q1"], |
| "measurable": "PROXY", |
| "reasons": "Proves: ordinal coping. Cannot prove: full rCSI score.", |
| "result_ids": ["rcsi_proxy"], |
| } |
| } |
| indicator_defs = { |
| "rcsi": { |
| "label": "Reduced Coping Strategies Index", |
| "definition": "Measures food insecurity via coping behaviour frequency.", |
| "cluster": "Food Security", |
| } |
| } |
|
|
| yaml_path = assemble_spec_yaml(tmp_path, "vasyr_2023", route, bind_results, indicator_defs) |
|
|
| assert yaml_path.exists() |
| assert yaml_path.name == "analysis_spec_vasyr_2023.yaml" |
|
|
| data = yaml.safe_load(yaml_path.read_text()) |
| assert data["dataset"] == "vasyr_2023" |
| assert data["unit_of_analysis"] == "key_informant" |
| assert "rcsi" in data["indicators"] |
| ind = data["indicators"]["rcsi"] |
| assert ind["measurable"] == "PROXY" |
| assert ind["definition"] == "Measures food insecurity via coping behaviour frequency." |
| assert ind["variables"] == ["cope_q1"] |
| assert ind["reasons"] == "Proves: ordinal coping. Cannot prove: full rCSI score." |
| assert ind["label"] == "Reduced Coping Strategies Index" |
|
|
|
|
| def test_assemble_spec_yaml_result_ids_is_catalog_slug(tmp_path): |
| """result_ids must be the catalog slug (the dict key), never the bind call's value. |
| |
| The bind call leaks dataset variable names into result_ids; code overrides it so the |
| 'Indicator name in the analysis' column always shows the stable catalog slug. |
| """ |
| from core.spec import assemble_spec_yaml |
|
|
| route = {"sectors": ["WASH"], "lens": [], "type": []} |
| bind_results = { |
| "jmp_water_safely_managed": { |
| "indicator_id": "jmp_water_safely_managed", |
| "variables": ["main_water_source_now"], |
| "measurable": "NOT_MEASURABLE", |
| "reasons": "Requires on-premises + availability + E. coli — none collected.", |
| |
| "result_ids": ["main_water_source_now"], |
| } |
| } |
| indicator_defs = { |
| "jmp_water_safely_managed": { |
| "label": "JMP Drinking Water — Safely Managed", |
| "definition": "Improved source on premises, available, free of contamination.", |
| "cluster": "wash", |
| } |
| } |
|
|
| yaml_path = assemble_spec_yaml(tmp_path, "vasyr_2023", route, bind_results, indicator_defs) |
| data = yaml.safe_load(yaml_path.read_text()) |
| ind = data["indicators"]["jmp_water_safely_managed"] |
| assert ind["result_ids"] == ["jmp_water_safely_managed"] |
|
|
|
|
| def test_assemble_spec_yaml_dimension_uses_cluster(tmp_path): |
| from core.spec import assemble_spec_yaml |
|
|
| route = {"sectors": ["WASH"], "lens": [], "type": []} |
| bind_results = { |
| "jmp_water_basic": { |
| "indicator_id": "jmp_water_basic", |
| "variables": ["water_src"], |
| "measurable": "MEASURABLE", |
| "reasons": "Proves: JMP basic access. Cannot prove: safely managed.", |
| "result_ids": ["jmp_basic"], |
| } |
| } |
| indicator_defs = { |
| "jmp_water_basic": { |
| "label": "JMP Drinking Water — Basic", |
| "definition": "Access to an improved source within 30 minutes.", |
| "cluster": "WASH", |
| } |
| } |
|
|
| yaml_path = assemble_spec_yaml(tmp_path, "test_slug", route, bind_results, indicator_defs) |
| data = yaml.safe_load(yaml_path.read_text()) |
|
|
| assert data["indicators"]["jmp_water_basic"]["dimension"] == "sector::WASH" |
| assert data["step1_framework_route"]["sector"] == "WASH" |
|
|
|
|
| def test_render_spec_md_calls_render_script(monkeypatch, tmp_path): |
| from core import spec as spec_mod |
|
|
| calls = [] |
| monkeypatch.setattr(spec_mod, "run_skill_script_raw", |
| lambda name, args: (calls.append((name, args)) or "# rendered md")) |
|
|
| spec_yaml = tmp_path / "analysis_spec_test.yaml" |
| spec_yaml.write_text("dataset: test\nindicators: {}") |
|
|
| md_path = spec_mod.render_spec_md(spec_yaml, tmp_path) |
|
|
| assert calls[0][0] == "render_spec.py" |
| assert str(spec_yaml) in calls[0][1] |
| assert md_path.exists() |
| assert md_path.read_text() == "# rendered md" |
| assert md_path.name == "analysis_spec_test.md" |
|
|