Skip to content

Commit

Permalink
added system test and unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ZohebShaikh committed Sep 6, 2024
1 parent b5bb825 commit 96ffe70
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 17 deletions.
5 changes: 2 additions & 3 deletions src/blueapi/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,8 @@ def get_task(self, task_id: str) -> TrackableTask[Task]:
Returns:
TrackableTask[Task]: Task details
"""
response = self._rest.get_task(task_id)
assert isinstance(response, TrackableTask)
return response
assert task_id != "", "Task ID cannot be empty"
return self._rest.get_task(task_id)

def get_all_task(self) -> TasksListResponse:
"""
Expand Down
70 changes: 58 additions & 12 deletions tests/system_tests/test_blueapi_system.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import time
from pathlib import Path

import pytest
Expand All @@ -9,7 +10,8 @@
BlueapiClient,
BlueskyRemoteControlError,
)
from blueapi.config import ApplicationConfig
from blueapi.client.event_bus import AnyEvent
from blueapi.config import ApplicationConfig, StompConfig
from blueapi.service.model import (
DeviceResponse,
EnvironmentResponse,
Expand All @@ -18,7 +20,7 @@
TasksListResponse,
WorkerTask,
)
from blueapi.worker.event import TaskStatusEnum, WorkerState
from blueapi.worker.event import TaskStatus, TaskStatusEnum, WorkerEvent, WorkerState
from blueapi.worker.task import Task
from blueapi.worker.task_worker import TrackableTask

Expand All @@ -33,6 +35,11 @@ def client() -> BlueapiClient:
return BlueapiClient.from_config(config=ApplicationConfig())


@pytest.fixture
def client_with_stomp() -> BlueapiClient:
return BlueapiClient.from_config(config=ApplicationConfig(stomp=StompConfig()))


@pytest.fixture
def expected_plans() -> PlanResponse:
return TypeAdapter(PlanResponse).validate_json(
Expand All @@ -59,7 +66,7 @@ def test_get_plans_by_name(client: BlueapiClient, expected_plans: PlanResponse):
def test_get_non_existent_plan(client: BlueapiClient):
with pytest.raises(KeyError) as exception:
client.get_plan("Not exists")
assert exception.value.args[0] == ("{'detail': 'Item not found'}")
assert str(exception) == ("{'detail': 'Item not found'}")


def test_get_devices(client: BlueapiClient, expected_devices: DeviceResponse):
Expand All @@ -74,7 +81,7 @@ def test_get_device_by_name(client: BlueapiClient, expected_devices: DeviceRespo
def test_get_non_existent_device(client: BlueapiClient):
with pytest.raises(KeyError) as exception:
assert client.get_device("Not exists")
assert exception.value.args[0] == ("{'detail': 'Item not found'}")
assert str(exception) == ("{'detail': 'Item not found'}")


def test_create_task_and_delete_task_by_id(client: BlueapiClient):
Expand All @@ -85,7 +92,7 @@ def test_create_task_and_delete_task_by_id(client: BlueapiClient):
def test_create_task_validation_error(client: BlueapiClient):
with pytest.raises(KeyError) as exception:
client.create_task(Task(name="Not-exists", params={"Not-exists": 0.0}))
assert exception.value.args[0] == ("{'detail': 'Item not found'}")
assert str(exception) == ("{'detail': 'Item not found'}")


def test_get_all_tasks(client: BlueapiClient):
Expand Down Expand Up @@ -121,13 +128,13 @@ def test_get_task_by_id(client: BlueapiClient):
def test_get_non_existent_task(client: BlueapiClient):
with pytest.raises(KeyError) as exception:
client.get_task("Not-exists")
assert exception.value.args[0] == "{'detail': 'Item not found'}"
assert str(exception) == "{'detail': 'Item not found'}"


def test_delete_non_existent_task(client: BlueapiClient):
with pytest.raises(KeyError) as exception:
client.clear_task("Not-exists")
assert exception.value.args[0] == "{'detail': 'Item not found'}"
assert str(exception) == "{'detail': 'Item not found'}"


def test_put_worker_task(client: BlueapiClient):
Expand All @@ -148,7 +155,7 @@ def test_put_worker_task_fails_if_not_idle(client: BlueapiClient):

with pytest.raises(BlueskyRemoteControlError) as exception:
client.start_task(WorkerTask(task_id=small_task.task_id))
assert exception.value.args[0] == "<Response [409]>"
assert str(exception) == "<Response [409]>"
client.abort()
client.clear_task(small_task.task_id)
client.clear_task(long_task.task_id)
Expand All @@ -161,11 +168,11 @@ def test_get_worker_state(client: BlueapiClient):
def test_set_state_transition_error(client: BlueapiClient):
with pytest.raises(BlueskyRemoteControlError) as exception:
client.resume()
assert exception.value.args[0] == "<Response [400]>"
assert str(exception) == "<Response [400]>"

with pytest.raises(BlueskyRemoteControlError) as exception:
client.pause()
assert exception.value.args[0] == "<Response [400]>"
assert str(exception) == "<Response [400]>"


def test_get_task_by_status(client: BlueapiClient):
Expand All @@ -186,10 +193,10 @@ def test_get_task_by_status(client: BlueapiClient):

client.start_task(WorkerTask(task_id=task_1.task_id))
while not client.get_task(task_1.task_id).is_complete:
...
time.sleep(0.1)
client.start_task(WorkerTask(task_id=task_2.task_id))
while not client.get_task(task_2.task_id).is_complete:
...
time.sleep(0.1)
task_by_completed_request = requests.get(
client._rest._url("/tasks"), params={"task_status": TaskStatusEnum.COMPLETE}
)
Expand All @@ -205,6 +212,45 @@ def test_get_task_by_status(client: BlueapiClient):
client.clear_task(task_id=task_2.task_id)


def test_progress_wit_stomp(client_with_stomp: BlueapiClient):
all_events: list[AnyEvent] = []

def on_event(event: AnyEvent):
all_events.append(event)

client_with_stomp.run_task(_SIMPLE_TASK, on_event=on_event)
assert isinstance(all_events[0], WorkerEvent) and all_events[0].task_status
task_id = all_events[0].task_status.task_id
running_event = WorkerEvent(
state=WorkerState.RUNNING,
task_status=TaskStatus(
task_id=task_id,
task_complete=False,
task_failed=False,
),
)
pending_event = WorkerEvent(
state=WorkerState.IDLE,
task_status=TaskStatus(
task_id=task_id,
task_complete=False,
task_failed=False,
),
)
complete_event = WorkerEvent(
state=WorkerState.IDLE,
task_status=TaskStatus(
task_id=task_id,
task_complete=True,
task_failed=False,
),
)
assert running_event in all_events
assert pending_event in all_events
assert complete_event in all_events
assert len(all_events) == 3


def test_get_current_state_of_environment(client: BlueapiClient):
assert client.get_environment() == EnvironmentResponse(initialized=True)

Expand Down
17 changes: 16 additions & 1 deletion tests/unit_tests/client/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
PlanModel,
PlanResponse,
TaskResponse,
TasksListResponse,
WorkerTask,
)
from blueapi.worker import ProgressEvent, Task, TrackableTask, WorkerEvent, WorkerState
Expand All @@ -35,6 +36,7 @@
)
DEVICE = DeviceModel(name="foo", protocols=[])
TASK = TrackableTask(task_id="foo", task=Task(name="bar", params={}))
TASKS = TasksListResponse(tasks=[TASK])
ACTIVE_TASK = WorkerTask(task_id="bar")
ENV = EnvironmentResponse(initialized=True)
COMPLETE_EVENT = WorkerEvent(
Expand Down Expand Up @@ -65,6 +67,7 @@ def mock_rest() -> BlueapiRestClient:
mock.get_device.return_value = DEVICE
mock.get_state.return_value = WorkerState.IDLE
mock.get_task.return_value = TASK
mock.get_all_task.return_value = TASKS
mock.get_active_task.return_value = ACTIVE_TASK
mock.get_environment.return_value = ENV
mock.delete_environment.return_value = EnvironmentResponse(initialized=False)
Expand Down Expand Up @@ -133,7 +136,7 @@ def test_get_task(client: BlueapiClient):
assert client.get_task("foo") == TASK


def test_get_nonexistant_task(
def test_get_nonexistent_task(
client: BlueapiClient,
mock_rest: Mock,
):
Expand All @@ -142,6 +145,18 @@ def test_get_nonexistant_task(
client.get_task("baz")


def test_get_task_with_empty_id(client: BlueapiClient):
with pytest.raises(AssertionError) as exc:
client.get_task("")
assert str(exc) == "Task ID cannot be empty"


def test_get_all_tasks(
client: BlueapiClient,
):
assert client.get_all_task() == TASKS


def test_create_task(
client: BlueapiClient,
mock_rest: Mock,
Expand Down
33 changes: 32 additions & 1 deletion tests/unit_tests/service/test_rest_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@

from blueapi.core.bluesky_types import Plan
from blueapi.service import main
from blueapi.service.model import DeviceModel, PlanModel, StateChangeRequest, WorkerTask
from blueapi.service.model import (
DeviceModel,
PlanModel,
StateChangeRequest,
WorkerTask,
)
from blueapi.worker.event import WorkerState
from blueapi.worker.task import Task
from blueapi.worker.task_worker import TrackableTask
Expand Down Expand Up @@ -379,6 +384,32 @@ def test_get_task(get_task_by_id: MagicMock, client: TestClient):
}


@patch("blueapi.service.interface.get_tasks")
def test_get_all_task(get_all_tasks: MagicMock, client: TestClient):
task_id = str(uuid.uuid4())
tasks = [
TrackableTask(
task_id=task_id,
task=Task(name="third_task"),
)
]

get_all_tasks.return_value = tasks
response = client.get("/tasks")
assert response.status_code == status.HTTP_200_OK
assert response.json() == {
"tasks": [
{
"task_id": task_id,
"task": {"name": "third_task", "params": {}},
"is_complete": False,
"is_pending": True,
"errors": [],
}
]
}


@patch("blueapi.service.interface.get_task_by_id")
def test_get_task_error(get_task_by_id_mock: MagicMock, client: TestClient):
task_id = 567
Expand Down

0 comments on commit 96ffe70

Please sign in to comment.