Skip to content

Commit 4290a6e

Browse files
Add integration tests for RFDetr models (#2673)
1 parent 6143d00 commit 4290a6e

3 files changed

Lines changed: 191 additions & 0 deletions

File tree

tests/inference/hosted_platform_tests/conftest.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ class PlatformEnvironment(Enum):
9090
"multi_class_classification": "vehicle-classification-eapcd/2",
9191
"yolov8n-640": "yolov8n-640",
9292
"yolov8n-pose-640": "yolov8n-pose-640",
93+
"rfdetr-od": "rfdetr-nano",
94+
"rfdetr-is": "rfdetr-seg-nano",
9395
},
9496
PlatformEnvironment.ROBOFLOW_STAGING_LAMBDA: {
9597
"object-detection": "eye-detection/35",
@@ -98,6 +100,8 @@ class PlatformEnvironment(Enum):
98100
"multi_class_classification": "car-classification/23",
99101
"yolov8n-640": "microsoft-coco-obj-det/8",
100102
"yolov8n-pose-640": "microsoft-coco-pose/1",
103+
"rfdetr-od": "rfdetr-nano",
104+
"rfdetr-is": "asl-instance-seg/160",
101105
},
102106
}
103107
MODELS_TO_BE_USED[PlatformEnvironment.ROBOFLOW_STAGING_SERVERLESS] = MODELS_TO_BE_USED[
@@ -217,6 +221,16 @@ def segmentation_model_id(platform_environment: PlatformEnvironment) -> str:
217221
return MODELS_TO_BE_USED[platform_environment]["instance-segmentation"]
218222

219223

224+
@pytest.fixture(scope="session")
225+
def rfdetr_od_model_id(platform_environment: PlatformEnvironment) -> str:
226+
return MODELS_TO_BE_USED[platform_environment]["rfdetr-od"]
227+
228+
229+
@pytest.fixture(scope="session")
230+
def rfdetr_is_model_id(platform_environment: PlatformEnvironment) -> str:
231+
return MODELS_TO_BE_USED[platform_environment]["rfdetr-is"]
232+
233+
220234
@pytest.fixture(scope="session")
221235
def target_project(platform_environment: PlatformEnvironment) -> str:
222236
return TARGET_PROJECTS_TO_BE_USED[platform_environment]
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import pytest
2+
3+
from inference_sdk import InferenceHTTPClient
4+
from tests.inference.hosted_platform_tests.conftest import IMAGE_URL, ROBOFLOW_API_KEY
5+
6+
7+
@pytest.mark.flaky(retries=4, delay=1)
8+
def test_infer_from_rfdetr_object_detection_model_when_valid_response_expected(
9+
object_detection_service_url: str,
10+
rfdetr_od_model_id: str,
11+
) -> None:
12+
# given
13+
client = InferenceHTTPClient(
14+
api_url=object_detection_service_url,
15+
api_key=ROBOFLOW_API_KEY,
16+
).select_api_v0()
17+
18+
# when
19+
response = client.infer(IMAGE_URL, model_id=rfdetr_od_model_id)
20+
21+
# then
22+
assert isinstance(response, dict), "Expected dict as response"
23+
assert "predictions" in response, "Expected 'predictions' key in response"
24+
assert (
25+
len(response["predictions"]) > 0
26+
), f"Expected at least one instance detected in {IMAGE_URL}"
27+
28+
29+
@pytest.mark.flaky(retries=4, delay=1)
30+
def test_infer_from_rfdetr_instance_segmentation_model_when_valid_response_expected(
31+
instance_segmentation_service_url: str,
32+
rfdetr_is_model_id: str,
33+
) -> None:
34+
# given
35+
client = InferenceHTTPClient(
36+
api_url=instance_segmentation_service_url,
37+
api_key=ROBOFLOW_API_KEY,
38+
).select_api_v0()
39+
40+
# when
41+
response = client.infer(IMAGE_URL, model_id=rfdetr_is_model_id)
42+
43+
# then
44+
assert isinstance(response, dict), "Expected dict as response"
45+
assert "predictions" in response, "Expected 'predictions' key in response"
46+
assert (
47+
len(response["predictions"]) > 0
48+
), f"Expected at least one instance detected in {IMAGE_URL}"
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import os
2+
3+
import pytest
4+
import requests
5+
6+
api_key = os.environ.get("API_KEY")
7+
port = os.environ.get("PORT", 9001)
8+
base_url = os.environ.get("BASE_URL", "http://localhost")
9+
10+
DOG_IMAGE_URL = "https://media.roboflow.com/dog.jpeg"
11+
12+
# Keep in sync with RFDETR_ALIASES in inference/models/aliases.py.
13+
# The legacy /{dataset_id}/{version_id} route cannot carry a slash-less alias —
14+
# clients (inference_sdk) resolve aliases before calling the server — so the
15+
# legacy tests hit the resolved model IDs, while the v1 /infer/* tests pass the
16+
# raw alias to exercise server-side alias resolution.
17+
RFDETR_DETECTION_ALIASES = {
18+
"rfdetr-base": "coco/36",
19+
"rfdetr-nano": "coco/38",
20+
"rfdetr-small": "coco/39",
21+
"rfdetr-medium": "coco/40",
22+
"rfdetr-large": "coco/50",
23+
"rfdetr-xlarge": "coco/47",
24+
"rfdetr-2xlarge": "coco/48",
25+
}
26+
RFDETR_SEGMENTATION_ALIASES = {
27+
"rfdetr-seg-preview": "coco-dataset-vdnr1/26",
28+
"rfdetr-seg-nano": "coco-dataset-vdnr1/41",
29+
"rfdetr-seg-small": "coco-dataset-vdnr1/36",
30+
"rfdetr-seg-medium": "coco-dataset-vdnr1/37",
31+
"rfdetr-seg-large": "coco-dataset-vdnr1/38",
32+
"rfdetr-seg-xlarge": "coco-dataset-vdnr1/39",
33+
"rfdetr-seg-2xlarge": "coco-dataset-vdnr1/40",
34+
}
35+
36+
37+
def bool_env(val):
38+
if isinstance(val, bool):
39+
return val
40+
return val.lower() in ["true", "1", "t", "y", "yes"]
41+
42+
43+
pytestmark = pytest.mark.skipif(
44+
bool_env(os.getenv("SKIP_RFDETR_TEST", False)),
45+
reason="Skipping RFDETR test",
46+
)
47+
48+
49+
def assert_instances_detected(response: requests.Response) -> None:
50+
response.raise_for_status()
51+
data = response.json()
52+
assert "predictions" in data, f"Response lacks 'predictions' key: {data}"
53+
assert (
54+
len(data["predictions"]) > 0
55+
), f"Expected at least one instance detected in {DOG_IMAGE_URL}"
56+
57+
58+
@pytest.mark.parametrize("alias", list(RFDETR_DETECTION_ALIASES))
59+
def test_rfdetr_detection_via_v1_endpoint(
60+
alias: str, clean_loaded_models_every_test_fixture
61+
) -> None:
62+
payload = {
63+
"model_id": alias,
64+
"image": {"type": "url", "value": DOG_IMAGE_URL},
65+
"api_key": api_key,
66+
}
67+
68+
response = requests.post(
69+
f"{base_url}:{port}/infer/object_detection",
70+
json=payload,
71+
)
72+
73+
assert_instances_detected(response)
74+
75+
76+
@pytest.mark.parametrize(
77+
"model_id",
78+
list(RFDETR_DETECTION_ALIASES.values()),
79+
ids=list(RFDETR_DETECTION_ALIASES),
80+
)
81+
def test_rfdetr_detection_via_legacy_endpoint(
82+
model_id: str, clean_loaded_models_every_test_fixture
83+
) -> None:
84+
response = requests.post(
85+
f"{base_url}:{port}/{model_id}",
86+
params={
87+
"api_key": api_key,
88+
"image": DOG_IMAGE_URL,
89+
},
90+
)
91+
92+
assert_instances_detected(response)
93+
94+
95+
@pytest.mark.parametrize("alias", list(RFDETR_SEGMENTATION_ALIASES))
96+
def test_rfdetr_segmentation_via_v1_endpoint(
97+
alias: str, clean_loaded_models_every_test_fixture
98+
) -> None:
99+
payload = {
100+
"model_id": alias,
101+
"image": {"type": "url", "value": DOG_IMAGE_URL},
102+
"api_key": api_key,
103+
}
104+
105+
response = requests.post(
106+
f"{base_url}:{port}/infer/instance_segmentation",
107+
json=payload,
108+
)
109+
110+
assert_instances_detected(response)
111+
112+
113+
@pytest.mark.parametrize(
114+
"model_id",
115+
list(RFDETR_SEGMENTATION_ALIASES.values()),
116+
ids=list(RFDETR_SEGMENTATION_ALIASES),
117+
)
118+
def test_rfdetr_segmentation_via_legacy_endpoint(
119+
model_id: str, clean_loaded_models_every_test_fixture
120+
) -> None:
121+
response = requests.post(
122+
f"{base_url}:{port}/{model_id}",
123+
params={
124+
"api_key": api_key,
125+
"image": DOG_IMAGE_URL,
126+
},
127+
)
128+
129+
assert_instances_detected(response)

0 commit comments

Comments
 (0)