professor-chen's picture
Sync from GitHub via hub-sync
57c13f4 verified
Raw History Blame Contribute Delete
3.56 kB
"""Tests d'intégration de l'API AstroDynamics."""
import pytest
def test_health_returns_loaded_model(client) -> None:
response = client.get("/health")
assert response.status_code == 200
payload = response.json()
assert payload["status"] == "ok"
assert payload["environment"] == "LunarLander-v3"
assert payload["algorithm"] == "DQN"
assert payload["model"] == "dqn_lunarlander_final.zip"
@pytest.mark.parametrize("endpoint", ["/play", "/predict"])
def test_prediction_returns_valid_action(client, endpoint: str) -> None:
response = client.post(
endpoint,
json={
"observation": [
0.0, # position x
1.0, # position y
0.0, # vitesse x
-0.2, # vitesse y
0.0, # angle
0.0, # vitesse angulaire
0.0, # contact jambe gauche
0.0, # contact jambe droite
]
},
)
assert response.status_code == 200
payload = response.json()
assert payload["action"] in {0, 1, 2, 3}
assert isinstance(payload["action_label"], str)
assert len(payload["q_values"]) == 4
assert all(isinstance(value, float) for value in payload["q_values"])
assert isinstance(payload["circumstance"], str)
@pytest.mark.parametrize(
"observation",
[
[],
[0.0] * 7,
[0.0] * 9,
],
)
def test_prediction_rejects_invalid_observation_length(
client,
observation: list[float],
) -> None:
response = client.post(
"/predict",
json={"observation": observation},
)
assert response.status_code == 422
def test_metrics_are_initially_empty(client) -> None:
response = client.get("/metrics")
assert response.status_code == 200
payload = response.json()
assert payload["summary"]["number_of_episodes"] == 0
assert payload["summary"]["mean_reward"] is None
assert payload["summary"]["std_reward"] is None
assert payload["episodes"] == []
assert payload["action_distribution"] == {}
assert payload["decisions_by_circumstance"] == {}
@pytest.mark.integration
def test_episode_is_played_and_persisted(client) -> None:
"""
Joue un véritable épisode avec le modèle sauvegardé.
L'animation est désactivée pour accélérer la CI et limiter la RAM.
"""
response = client.post(
"/episodes",
json={
"seed": 42,
"capture_animation": False,
"frame_stride": 5,
},
)
assert response.status_code == 200
episode = response.json()
assert len(episode["episode_id"]) == 32
assert episode["seed"] == 42
assert episode["steps"] > 0
assert isinstance(episode["reward"], float)
assert isinstance(episode["success"], bool)
assert episode["animation_url"] is None
assert sum(episode["action_counts"].values()) == episode["steps"]
metrics_response = client.get("/metrics")
assert metrics_response.status_code == 200
metrics = metrics_response.json()
assert metrics["summary"]["number_of_episodes"] == 1
assert metrics["episodes"][0]["episode_id"] == episode["episode_id"]
assert metrics["episodes"][0]["seed"] == 42
assert metrics["episodes"][0]["reward"] == pytest.approx(
episode["reward"]
)
def test_unknown_animation_returns_404(client) -> None:
unknown_id = "0" * 32
response = client.get(
f"/episodes/{unknown_id}/animation"
)
assert response.status_code == 404