test_api_routes.py
1 from pathlib import Path 2 3 import pytest 4 import requests 5 6 import mlflow 7 from mlflow.server import handlers 8 from mlflow.server.fastapi_app import app 9 from mlflow.server.handlers import initialize_backend_stores 10 11 from tests.helper_functions import get_safe_port 12 from tests.tracking.integration_test_utils import ServerThread 13 14 15 @pytest.fixture 16 def tracking_server(db_uri: str, tmp_path: Path): 17 handlers._tracking_store = None 18 handlers._model_registry_store = None 19 initialize_backend_stores(db_uri, default_artifact_root=tmp_path.as_uri()) 20 21 with ServerThread(app, get_safe_port()) as url: 22 mlflow.set_tracking_uri(url) 23 yield url 24 mlflow.set_tracking_uri(None) 25 26 27 def test_generate_demo_route_creates_data(tracking_server): 28 response = requests.post(f"{tracking_server}/ajax-api/3.0/mlflow/demo/generate") 29 30 assert response.status_code == 200 31 data = response.json() 32 assert data["status"] == "created" 33 assert data["experiment_id"] is not None 34 assert len(data["features_generated"]) > 0 35 assert data["navigation_url"] is not None 36 37 38 def test_generate_demo_route_idempotent(tracking_server): 39 response1 = requests.post(f"{tracking_server}/ajax-api/3.0/mlflow/demo/generate") 40 assert response1.status_code == 200 41 data1 = response1.json() 42 assert data1["status"] == "created" 43 44 response2 = requests.post(f"{tracking_server}/ajax-api/3.0/mlflow/demo/generate") 45 assert response2.status_code == 200 46 data2 = response2.json() 47 assert data2["status"] == "exists" 48 assert data2["features_generated"] == [] 49 50 51 def test_delete_demo_route_removes_data(tracking_server): 52 requests.post(f"{tracking_server}/ajax-api/3.0/mlflow/demo/generate") 53 54 response = requests.post(f"{tracking_server}/ajax-api/3.0/mlflow/demo/delete") 55 56 assert response.status_code == 200 57 data = response.json() 58 assert data["status"] == "deleted" 59 assert len(data["features_deleted"]) > 0 60 61 62 def test_delete_demo_route_when_no_data(tracking_server): 63 response = requests.post(f"{tracking_server}/ajax-api/3.0/mlflow/demo/delete") 64 65 assert response.status_code == 200 66 data = response.json() 67 assert data["status"] == "deleted" 68 assert data["features_deleted"] == [] 69 70 71 def test_generate_after_delete_regenerates(tracking_server): 72 response1 = requests.post(f"{tracking_server}/ajax-api/3.0/mlflow/demo/generate") 73 assert response1.json()["status"] == "created" 74 75 requests.post(f"{tracking_server}/ajax-api/3.0/mlflow/demo/delete") 76 77 response2 = requests.post(f"{tracking_server}/ajax-api/3.0/mlflow/demo/generate") 78 assert response2.status_code == 200 79 data = response2.json() 80 assert data["status"] == "created" 81 assert len(data["features_generated"]) > 0 82 83 84 def test_get_demo_endpoints_returns_routes(): 85 from mlflow.server.handlers import get_demo_endpoints 86 87 endpoints = get_demo_endpoints() 88 89 assert len(endpoints) == 2 90 91 paths = [path for path, _, _ in endpoints] 92 assert any("/mlflow/demo/generate" in path for path in paths) 93 assert any("/mlflow/demo/delete" in path for path in paths) 94 95 96 def test_get_endpoints_includes_demo(): 97 from mlflow.server.handlers import get_endpoints 98 99 endpoints = get_endpoints() 100 paths = [path for path, _, _ in endpoints] 101 102 assert any("/mlflow/demo/generate" in path for path in paths) 103 assert any("/mlflow/demo/delete" in path for path in paths)