jester1177/cloudnative-devops-debug-env
0
1"""Endpoint tests for the FastAPI server."""2 3from fastapi.testclient import TestClient4 5from server.app import app6 7client = TestClient(app)8 9 10def test_root_landing_page():11 response = client.get("/")12 assert response.status_code == 20013 assert "text/html" in response.headers.get("content-type", "")14 assert "CI/CD" in response.text15 16 17def test_health_endpoint():18 response = client.get("/health")19 assert response.status_code == 20020 data = response.json()21 assert data["status"] == "healthy"22 23 24def test_info_returns_all_tasks():25 info = client.get("/info")26 assert info.status_code == 20027 data = info.json()28 assert len(data.get("tasks", [])) >= 629 assert "action_space" in data30 assert "observation_space" in data31 32 33def test_tasks_endpoint():34 tasks = client.get("/tasks")35 assert tasks.status_code == 20036 data = tasks.json()37 assert len(data.get("tasks", [])) >= 638 task_ids = [t["id"] for t in data["tasks"]]39 assert "dockerfile_syntax" in task_ids40 assert "multi_stage_pipeline_matrix" in task_ids41 42 43def test_reset_default():44 resp = client.post("/reset", json={})45 assert resp.status_code == 20046 data = resp.json()47 assert "observation" in data48 obs = data["observation"]49 assert obs["total_issues"] >= 150 assert obs["step_number"] == 051 52 53def test_reset_specific_task():54 resp = client.post("/reset", json={"task_id": "dockerfile_syntax", "scenario_id": "typo_filename"})55 assert resp.status_code == 20056 obs = resp.json()["observation"]57 assert obs["task_id"] == "dockerfile_syntax"58 59 60def test_reset_with_seed():61 resp1 = client.post("/reset", json={"seed": 99})62 resp2 = client.post("/reset", json={"seed": 99})63 assert resp1.json()["observation"]["task_id"] == resp2.json()["observation"]["task_id"]64 65 66def test_reset_invalid_task():67 resp = client.post("/reset", json={"task_id": "nonexistent_task"})68 assert resp.status_code == 40069 70 71def test_state_without_reset():72 # Force a fresh app state by not resetting — this test relies on prior reset73 # Just verify the endpoint returns 200 (prior test did a reset)74 resp = client.get("/state")75 assert resp.status_code == 20076 data = resp.json()77 assert "observation" in data78 assert "episode_reward" in data79 80 81def test_step_edit_file():82 client.post("/reset", json={"task_id": "dockerfile_syntax", "scenario_id": "typo_filename"})83 resp = client.post("/step", json={84 "action": {85 "action_type": "edit_file",86 "edits": [{87 "file_path": "Dockerfile",88 "old_content": "COPY requirments.txt .",89 "new_content": "COPY requirements.txt .",90 }],91 }92 })93 assert resp.status_code == 20094 data = resp.json()95 assert data["reward"] > 096 assert data["info"]["issues_fixed"] >= 197 98 99def test_step_submit():100 client.post("/reset", json={"task_id": "dockerfile_syntax"})101 resp = client.post("/step", json={"action": {"action_type": "submit"}})102 assert resp.status_code == 200103 assert resp.json()["done"] is True104 105 106def test_step_request_hint():107 client.post("/reset", json={"task_id": "dockerfile_syntax"})108 resp = client.post("/step", json={"action": {"action_type": "request_hint"}})109 assert resp.status_code == 200110 obs = resp.json()["observation"]111 assert obs["hints_used"] == 1112 assert "Hint" in (obs.get("last_action_feedback") or "")113 114 115def test_grader_endpoint():116 trajectory = [117 {"step": 1, "action": {"action_type": "edit_file", "edits": [{"file_path": "Dockerfile"}]},118 "reward": 0.3, "done": True, "info": {"issues_fixed": 1, "issues_total": 1}},119 ]120 resp = client.post("/grader", json={"task_id": "dockerfile_syntax", "trajectory": trajectory})121 assert resp.status_code == 200122 result = resp.json()["result"]123 assert result["score"] == 1.0124 125 126def test_grader_empty_trajectory():127 resp = client.post("/grader", json={"task_id": "dockerfile_syntax", "trajectory": []})128 assert resp.status_code == 200129 assert resp.json()["result"]["score"] == 0.0130 131 132def test_full_episode_via_api():133 """Full episode: reset -> edit -> submit -> verify score."""134 client.post("/reset", json={"task_id": "dockerfile_syntax", "scenario_id": "typo_filename"})135 136 client.post("/step", json={137 "action": {138 "action_type": "edit_file",139 "edits": [{140 "file_path": "Dockerfile",141 "old_content": "COPY requirments.txt .",142 "new_content": "COPY requirements.txt .",143 }],144 }145 })146 147 resp = client.post("/step", json={"action": {"action_type": "submit"}})148 assert resp.json()["done"] is True149 150 state = client.get("/state")151 assert state.json()["done"] is True152 assert state.json()["episode_reward"] > 0153 