Skip to content

Commit d2224c4

Browse files
committed
update/refactor tests
1 parent 7b66677 commit d2224c4

3 files changed

Lines changed: 97 additions & 140 deletions

File tree

openml/testing.py

Lines changed: 38 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@
1111
import unittest
1212
from pathlib import Path
1313
from typing import ClassVar
14-
from urllib.parse import urljoin
1514

1615
import requests
1716

1817
import openml
1918
from openml._api import HTTPCache, HTTPClient, MinIOClient
20-
from openml.enums import RetryPolicy
19+
from openml.enums import APIVersion, RetryPolicy
2120
from openml.exceptions import OpenMLServerException
2221
from openml.tasks import TaskType
2322

@@ -283,90 +282,53 @@ def _check_fold_timing_evaluations( # noqa: PLR0913
283282

284283

285284
class TestAPIBase(unittest.TestCase):
286-
server: str
287-
base_url: str
288-
api_key: str
289285
retries: int
290286
retry_policy: RetryPolicy
291-
dir: str
292287
ttl: int
288+
cache_dir: Path
293289
cache: HTTPCache
294-
http_client: HTTPClient
290+
http_clients: dict[APIVersion, HTTPClient]
291+
minio_client: MinIOClient
292+
current_api_version: APIVersion | None
295293

296294
def setUp(self) -> None:
297-
self.server = "https://test.openml.org/"
298-
self.base_url = "api/v1/xml"
299-
self.api_key = "normaluser"
300-
self.retries = 3
301-
self.retry_policy = RetryPolicy.HUMAN
302-
self.dir = "test_cache"
303-
self.ttl = 60 * 60 * 24 * 7
304-
305-
self.cache = self._get_http_cache(
306-
path=Path(self.dir),
307-
ttl=self.ttl,
308-
)
309-
self.http_client = self._get_http_client(
310-
server=self.server,
311-
base_url=self.base_url,
312-
api_key=self.api_key,
313-
retries=self.retries,
314-
retry_policy=self.retry_policy,
315-
cache=self.cache,
316-
)
317-
self.minio_client = self._get_minio_client(path=Path(self.dir))
295+
config = openml._backend.get_config()
318296

319-
if self.cache.path.exists():
320-
shutil.rmtree(self.cache.path)
321-
322-
def tearDown(self) -> None:
323-
if self.cache.path.exists():
324-
shutil.rmtree(self.cache.path)
297+
self.retries = config.connection.retries
298+
self.retry_policy = config.connection.retry_policy
299+
self.ttl = config.cache.ttl
300+
self.current_api_version = None
325301

326-
def _get_http_cache(
327-
self,
328-
path: Path,
329-
ttl: int,
330-
) -> HTTPCache:
331-
return HTTPCache(
332-
path=path,
333-
ttl=ttl,
334-
)
302+
abspath_this_file = Path(inspect.getfile(self.__class__)).absolute()
303+
self.cache_dir = abspath_this_file.parent.parent / "files"
304+
if not self.cache_dir.is_dir():
305+
raise ValueError(
306+
f"Cannot find test cache dir, expected it to be {self.cache_dir}!",
307+
)
335308

336-
def _get_http_client( # noqa: PLR0913
337-
self,
338-
server: str,
339-
base_url: str,
340-
api_key: str,
341-
retries: int,
342-
retry_policy: RetryPolicy,
343-
cache: HTTPCache | None = None,
344-
) -> HTTPClient:
345-
return HTTPClient(
346-
server=server,
347-
base_url=base_url,
348-
api_key=api_key,
349-
retries=retries,
350-
retry_policy=retry_policy,
351-
cache=cache,
309+
self.cache = HTTPCache(
310+
path=self.cache_dir,
311+
ttl=self.ttl,
352312
)
353-
354-
def _get_minio_client(
355-
self,
356-
path: Path | None = None,
357-
) -> MinIOClient:
358-
return MinIOClient(path=path)
359-
360-
def _get_url(
361-
self,
362-
server: str | None = None,
363-
base_url: str | None = None,
364-
path: str | None = None,
365-
) -> str:
366-
server = server if server else self.server
367-
base_url = base_url if base_url else self.base_url
368-
path = path if path else ""
369-
return urljoin(self.server, urljoin(self.base_url, path))
313+
self.http_clients = {
314+
APIVersion.V1: HTTPClient(
315+
server="https://test.openml.org/",
316+
base_url="api/v1/xml/",
317+
api_key="normaluser",
318+
retries=self.retries,
319+
retry_policy=self.retry_policy,
320+
cache=self.cache,
321+
),
322+
APIVersion.V2: HTTPClient(
323+
server="http://localhost:8002/",
324+
base_url="",
325+
api_key="",
326+
retries=self.retries,
327+
retry_policy=self.retry_policy,
328+
cache=self.cache,
329+
),
330+
}
331+
self.minio_client = MinIOClient(path=self.cache_dir)
370332

371333

372334
def check_task_existence(

tests/test_api/test_http.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,22 @@
44
import pytest
55
from openml.testing import TestAPIBase
66
import os
7+
from urllib.parse import urljoin
8+
from openml.enums import APIVersion
79

810

911
class TestHTTPClient(TestAPIBase):
12+
def setUp(self):
13+
super().setUp()
14+
self.http_client = self.http_clients[APIVersion.V1]
15+
16+
def _prepare_url(self, path: str | None = None) -> str:
17+
server = self.http_client.server
18+
base_url = self.http_client.base_url
19+
return urljoin(server, urljoin(base_url, path))
20+
1021
def test_cache(self):
11-
url = self._get_url(path="task/31")
22+
url = self._prepare_url(path="task/31")
1223
params = {"param1": "value1", "param2": "value2"}
1324

1425
key = self.cache.get_key(url, params)
@@ -18,6 +29,7 @@ def test_cache(self):
1829
"test",
1930
"api",
2031
"v1",
32+
"xml",
2133
"task",
2234
"31",
2335
"param1=value1&param2=value2",
@@ -68,7 +80,7 @@ def test_get_with_cache_creates_cache(self):
6880

6981
# verify cache directory structure exists
7082
cache_key = self.cache.get_key(
71-
self._get_url(path="task/1"),
83+
self._prepare_url(path="task/1"),
7284
{},
7385
)
7486
cache_path = self.cache._key_to_path(cache_key)
@@ -94,7 +106,7 @@ def test_get_cache_expires(self):
94106
self.cache.ttl = 1
95107
path = "task/1"
96108

97-
url = self._get_url(path=path)
109+
url = self._prepare_url(path=path)
98110
key = self.cache.get_key(url, {})
99111
cache_path = self.cache._key_to_path(key) / "meta.json"
100112

@@ -115,7 +127,7 @@ def test_get_cache_expires(self):
115127
def test_get_reset_cache(self):
116128
path = "task/1"
117129

118-
url = self._get_url(path=path)
130+
url = self._prepare_url(path=path)
119131
key = self.cache.get_key(url, {})
120132
cache_path = self.cache._key_to_path(key) / "meta.json"
121133

tests/test_api/test_versions.py

Lines changed: 43 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,13 @@
22
import pytest
33
from openml.testing import TestAPIBase
44
from openml._api import ResourceV1API, ResourceV2API, FallbackProxy
5-
from openml.enums import ResourceType
5+
from openml.enums import ResourceType, APIVersion
66
from openml.exceptions import OpenMLNotSupportedError
77

88

9-
class TestResourceV1API(TestAPIBase):
10-
def setUp(self):
11-
super().setUp()
12-
self.resource = ResourceV1API(self.http_client)
13-
self.resource.resource_type = ResourceType.TASK
14-
15-
@pytest.mark.uses_test_server()
16-
def test_publish_and_delete(self):
9+
@pytest.mark.uses_test_server()
10+
class TestResourceAPIBase(TestAPIBase):
11+
def _publish_and_delete(self):
1712
task_xml = """
1813
<oml:task_inputs xmlns:oml="http://openml.org/openml">
1914
<oml:task_type_id>5</oml:task_type_id>
@@ -22,30 +17,19 @@ def test_publish_and_delete(self):
2217
</oml:task_inputs>
2318
"""
2419

25-
task_id = None
26-
try:
27-
# Publish the task
28-
task_id = self.resource.publish(
29-
"task",
30-
files={"description": task_xml},
31-
)
32-
33-
# Get the task to verify it exists
34-
get_response = self.http_client.get(f"task/{task_id}")
35-
self.assertEqual(get_response.status_code, 200)
36-
37-
finally:
38-
# delete the task if it was created
39-
if task_id is not None:
40-
success = self.resource.delete(task_id)
41-
self.assertTrue(success)
20+
task_id = self.resource.publish(
21+
"task",
22+
files={"description": task_xml},
23+
)
24+
self.assertIsNotNone(task_id)
4225

26+
success = self.resource.delete(task_id)
27+
self.assertTrue(success)
4328

44-
@pytest.mark.uses_test_server()
45-
def test_tag_and_untag(self):
29+
def _tag_and_untag(self):
4630
resource_id = 1
4731
unique_indicator = str(time()).replace(".", "")
48-
tag = f"TestResourceV1API_test_tag_and_untag_{unique_indicator}"
32+
tag = f"{self.__class__.__name__}_test_tag_and_untag_{unique_indicator}"
4933

5034
tags = self.resource.tag(resource_id, tag)
5135
self.assertIn(tag, tags)
@@ -54,52 +38,51 @@ def test_tag_and_untag(self):
5438
self.assertNotIn(tag, tags)
5539

5640

57-
class TestResourceV2API(TestResourceV1API):
41+
class TestResourceV1API(TestResourceAPIBase):
5842
def setUp(self):
5943
super().setUp()
60-
61-
self.server = ""
62-
self.base_url = ""
63-
self.api_key = ""
64-
self.http_client = self._get_http_client(
65-
server=self.server,
66-
base_url=self.base_url,
67-
api_key=self.api_key,
68-
retries=self.retries,
69-
retry_policy=self.retry_policy,
70-
cache=self.cache,
71-
)
72-
73-
self.resource = ResourceV2API(self.http_client)
44+
http_client = self.http_clients[APIVersion.V1]
45+
self.resource = ResourceV1API(http_client)
7446
self.resource.resource_type = ResourceType.TASK
7547

76-
@pytest.mark.xfail(raises=OpenMLNotSupportedError)
7748
def test_publish_and_delete(self):
78-
super().test_tag_and_untag()
79-
49+
self._publish_and_delete()
8050

81-
@pytest.mark.xfail(raises=OpenMLNotSupportedError)
8251
def test_tag_and_untag(self):
83-
super().test_tag_and_untag()
52+
self._tag_and_untag()
8453

8554

86-
class TestResourceFallbackAPI(TestResourceV1API):
55+
class TestResourceV2API(TestResourceAPIBase):
8756
def setUp(self):
8857
super().setUp()
58+
http_client = self.http_clients[APIVersion.V2]
59+
self.resource = ResourceV2API(http_client)
60+
self.resource.resource_type = ResourceType.TASK
61+
62+
def test_publish_and_delete(self):
63+
with pytest.raises(OpenMLNotSupportedError):
64+
self._tag_and_untag()
65+
66+
def test_tag_and_untag(self):
67+
with pytest.raises(OpenMLNotSupportedError):
68+
self._tag_and_untag()
8969

90-
self.http_client_v2 = self._get_http_client(
91-
server="",
92-
base_url="",
93-
api_key="",
94-
retries=self.retries,
95-
retry_policy=self.retry_policy,
96-
cache=self.cache,
97-
)
9870

99-
resource_v1 = ResourceV1API(self.http_client)
71+
class TestResourceFallbackAPI(TestResourceAPIBase):
72+
def setUp(self):
73+
super().setUp()
74+
http_client_v1 = self.http_clients[APIVersion.V1]
75+
resource_v1 = ResourceV1API(http_client_v1)
10076
resource_v1.resource_type = ResourceType.TASK
10177

102-
resource_v2 = ResourceV2API(self.http_client_v2)
78+
http_client_v2 = self.http_clients[APIVersion.V2]
79+
resource_v2 = ResourceV2API(http_client_v2)
10380
resource_v2.resource_type = ResourceType.TASK
10481

10582
self.resource = FallbackProxy(resource_v2, resource_v1)
83+
84+
def test_publish_and_delete(self):
85+
self._publish_and_delete()
86+
87+
def test_tag_and_untag(self):
88+
self._tag_and_untag()

0 commit comments

Comments
 (0)