Spaces:
Sleeping
Sleeping
| """Tests for the prerequisite reading-path planner. | |
| Run: uv run pytest tests/test_planning.py | |
| """ | |
| from __future__ import annotations | |
| import pytest | |
| from researchpath.planning import plan_reading_path | |
| from researchpath.prerequisites import STATIC_PREREQUISITES | |
| def test_target_only_when_no_prereqs(): | |
| """A paper with no incoming edges should yield a one-step plan (just itself).""" | |
| plan = plan_reading_path("1312.5602") # DQN — no prereqs in the graph | |
| assert len(plan.steps) == 1 | |
| assert plan.steps[0].paper.arxiv_id == "1312.5602" | |
| def test_rainbow_full_chain(): | |
| """Rainbow with no prior knowledge requires DQN, Double DQN, PER, Dueling DQN, Rainbow. | |
| PER was added to the corpus and is one of Rainbow's six components, so it appears | |
| between Double DQN and Dueling DQN (year 2015 vs 2016 topo tie-break). | |
| """ | |
| plan = plan_reading_path("1710.02298") | |
| ids_in_order = [s.paper.arxiv_id for s in plan.steps] | |
| assert ids_in_order == ["1312.5602", "1509.06461", "1511.05952", "1511.06581", "1710.02298"] | |
| def test_known_set_truncates_chain(): | |
| """Knowing DQN should drop it from the Rainbow plan.""" | |
| plan = plan_reading_path("1710.02298", known_ids={"1312.5602"}) | |
| ids = {s.paper.arxiv_id for s in plan.steps} | |
| assert "1312.5602" not in ids | |
| assert "1710.02298" in ids | |
| # Double DQN, PER, Dueling DQN, Rainbow remain (PER now in corpus as Rainbow component) | |
| assert len(plan.steps) == 4 | |
| def test_known_target_yields_empty_plan(): | |
| """If the target is already 'known', no reading is needed.""" | |
| plan = plan_reading_path("1710.02298", known_ids={"1710.02298"}) | |
| assert plan.steps == () | |
| def test_topological_order_respects_edges(): | |
| """For every edge (A -> B), A must appear before B in the plan.""" | |
| plan = plan_reading_path("1710.02298") | |
| positions = {s.paper.arxiv_id: i for i, s in enumerate(plan.steps)} | |
| for edge in STATIC_PREREQUISITES: | |
| if edge.from_id in positions and edge.to_id in positions: | |
| assert positions[edge.from_id] < positions[edge.to_id], ( | |
| f"{edge.from_id} should precede {edge.to_id}" | |
| ) | |
| def test_unknown_target_raises(): | |
| with pytest.raises(ValueError): | |
| plan_reading_path("9999.99999") | |
| def test_render_text_contains_target_title(): | |
| plan = plan_reading_path("1710.02298") | |
| text = plan.render_text() | |
| assert "Rainbow" in text | |
| assert "1710.02298" in text | |