Skip to content

Commit

Permalink
added unit tests for stac api interaction #213
Browse files Browse the repository at this point in the history
  • Loading branch information
VincentVerelst committed Nov 28, 2024
1 parent 8df2ea3 commit a0bacdf
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 10 deletions.
15 changes: 5 additions & 10 deletions src/worldcereal/stac/stac_api_interaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,12 @@ def __init__(

self.auth = auth

self.client = pystac_client.Client.open(base_url)

self.bulk_size = bulk_size

def exists(self) -> bool:
client = pystac_client.Client.open(self.base_url)
return (
len(
[
c.id
for c in self.client.get_collections()
if c.id == self.collection_id
]
)
len([c.id for c in client.get_collections() if c.id == self.collection_id])
> 0
)

Expand Down Expand Up @@ -163,7 +156,9 @@ def _ingest_bulk(self, items: Iterable[pystac.Item]) -> dict:
"method": "upsert",
"items": {item.id: item.to_dict() for item in items},
}
response = requests.post(self._join_url(url_path), auth=self.auth, json=data)
response = requests.post(
url=self._join_url(url_path), auth=self.auth, json=data
)

expected_status = [
requests.status_codes.codes.ok,
Expand Down
131 changes: 131 additions & 0 deletions tests/worldcerealtests/test_stac_api_interaction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
from unittest.mock import MagicMock, patch

import pystac
import pytest
from requests.auth import AuthBase

from worldcereal.stac.stac_api_interaction import StacApiInteraction


@pytest.fixture
def mock_auth():
return MagicMock(spec=AuthBase)


def mock_stac_item(item_id):
item = MagicMock(spec=pystac.Item)
item.id = item_id
item.to_dict.return_value = {"id": item_id, "some_property": "value"}
return item


class TestStacApiInteraction:
@patch("requests.post")
@patch("worldcereal.stac.stac_api_interaction.StacApiInteraction.exists")
def test_upload_items_single_chunk(
self, mock_exists, mock_requests_post, mock_auth
):
"""Test bulk upload of STAC items in one single chunk."""

mock_requests_post.return_value.status_code = 200
mock_requests_post.return_value.json.return_value = {"status": "success"}
mock_requests_post.reason = "OK"

mock_exists.return_value = True

items = [mock_stac_item(f"item-{i}") for i in range(10)]

interaction = StacApiInteraction(
sensor="Sentinel1",
base_url="http://fake-stac-api",
auth=mock_auth,
bulk_size=10, # To ensure all 10 items are uploaded in one bulk
)
interaction.upload_items_bulk(items)

mock_requests_post.assert_called_with(
url=f"http://fake-stac-api/collections/{interaction.collection_id}/bulk_items",
auth=mock_auth,
json={
"method": "upsert",
"items": {item.id: item.to_dict() for item in items},
},
)
assert mock_requests_post.call_count == 1

@patch("requests.post")
@patch("worldcereal.stac.stac_api_interaction.StacApiInteraction.exists")
def test_upload_items_multiple_chunk(
self, mock_exists, mock_requests_post, mock_auth
):
"""Test bulk upload of STAC items in mulitiple chunks."""

mock_requests_post.return_value.status_code = 200
mock_requests_post.return_value.json.return_value = {"status": "success"}
mock_requests_post.reason = "OK"

mock_exists.return_value = True

items = [mock_stac_item(f"item-{i}") for i in range(10)]

interaction = StacApiInteraction(
sensor="Sentinel1",
base_url="http://fake-stac-api",
auth=mock_auth,
bulk_size=3, # This would require 4 chunk for 10 items
)
interaction.upload_items_bulk(items)

assert mock_requests_post.call_count == 4

expected_calls = [
{
"url": f"http://fake-stac-api/collections/{interaction.collection_id}/bulk_items",
"auth": mock_auth,
"json": {
"method": "upsert",
"items": {
"item-0": {"id": "item-0", "some_property": "value"},
"item-1": {"id": "item-1", "some_property": "value"},
"item-2": {"id": "item-2", "some_property": "value"},
},
},
},
{
"url": f"http://fake-stac-api/collections/{interaction.collection_id}/bulk_items",
"auth": mock_auth,
"json": {
"method": "upsert",
"items": {
"item-3": {"id": "item-3", "some_property": "value"},
"item-4": {"id": "item-4", "some_property": "value"},
"item-5": {"id": "item-5", "some_property": "value"},
},
},
},
{
"url": f"http://fake-stac-api/collections/{interaction.collection_id}/bulk_items",
"auth": mock_auth,
"json": {
"method": "upsert",
"items": {
"item-6": {"id": "item-6", "some_property": "value"},
"item-7": {"id": "item-7", "some_property": "value"},
"item-8": {"id": "item-8", "some_property": "value"},
},
},
},
{
"url": f"http://fake-stac-api/collections/{interaction.collection_id}/bulk_items",
"auth": mock_auth,
"json": {
"method": "upsert",
"items": {
"item-9": {"id": "item-9", "some_property": "value"},
},
},
},
]

for i, call in enumerate(mock_requests_post.call_args_list):
assert call[1] == expected_calls[i]

0 comments on commit a0bacdf

Please sign in to comment.