Skip to content

Commit 05150ae

Browse files
committed
test: Update tests for new exception hierarchy
1 parent 5cbc36f commit 05150ae

4 files changed

Lines changed: 54 additions & 26 deletions

File tree

tests/system_tests/test_blueapi_system.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
BlueapiRestClient,
1616
BlueskyRemoteControlError,
1717
BlueskyRequestError,
18+
NotFoundError,
1819
ServiceUnavailableError,
20+
UnauthorisedAccessError,
1921
)
2022
from blueapi.config import (
2123
ApplicationConfig,
@@ -217,7 +219,7 @@ def test_cannot_access_endpoints(
217219
"get_oidc_config"
218220
) # get_oidc_config can be accessed without auth
219221
for get_method in blueapi_rest_client_get_methods:
220-
with pytest.raises(BlueskyRemoteControlError, match=r"<Response \[401\]>"):
222+
with pytest.raises(UnauthorisedAccessError, match=r"<Response \[401\]>"):
221223
getattr(client_without_auth._rest, get_method)()
222224

223225

@@ -243,7 +245,7 @@ def test_get_plans_by_name(client: BlueapiClient, expected_plans: PlanResponse):
243245

244246

245247
def test_get_non_existent_plan(rest_client: BlueapiRestClient):
246-
with pytest.raises(KeyError, match="{'detail': 'Item not found'}"):
248+
with pytest.raises(NotFoundError):
247249
rest_client.get_plan("Not exists")
248250

249251

@@ -268,12 +270,12 @@ def test_get_device_by_name(
268270

269271

270272
def test_get_non_existent_device(rest_client: BlueapiRestClient):
271-
with pytest.raises(KeyError, match="{'detail': 'Item not found'}"):
273+
with pytest.raises(NotFoundError):
272274
rest_client.get_device("Not exists")
273275

274276

275277
def test_client_non_existent_device(client: BlueapiClient):
276-
with pytest.raises(AttributeError, match="No device named 'missing' available"):
278+
with pytest.raises(AttributeError):
277279
_ = client.devices.missing
278280

279281

@@ -295,7 +297,7 @@ def test_instrument_session_propagated(rest_client: BlueapiRestClient):
295297

296298

297299
def test_create_task_validation_error(rest_client: BlueapiRestClient):
298-
with pytest.raises(BlueskyRequestError, match="Internal Server Error"):
300+
with pytest.raises(BlueskyRequestError):
299301
rest_client.create_task(
300302
TaskRequest(
301303
name="Not-exists",
@@ -336,12 +338,12 @@ def test_get_task_by_id(rest_client: BlueapiRestClient):
336338

337339

338340
def test_get_non_existent_task(rest_client: BlueapiRestClient):
339-
with pytest.raises(KeyError, match="{'detail': 'Item not found'}"):
341+
with pytest.raises(NotFoundError):
340342
rest_client.get_task("Not-exists")
341343

342344

343345
def test_delete_non_existent_task(rest_client: BlueapiRestClient):
344-
with pytest.raises(KeyError, match="{'detail': 'Item not found'}"):
346+
with pytest.raises(NotFoundError):
345347
rest_client.clear_task("Not-exists")
346348

347349

tests/unit_tests/cli/test_cli.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,8 @@ def test_connection_error_caught_by_wrapper_func(
118118
def test_authentication_error_caught_by_wrapper_func(
119119
mock_requests: Mock, runner: CliRunner
120120
):
121-
mock_requests.side_effect = BlueskyRemoteControlError("<Response [401]>")
121+
mock_requests.side_effect = UnauthorisedAccessError(message="<Response [401]>")
122122
result = runner.invoke(main, ["controller", "plans"])
123-
124123
assert (
125124
result.output
126125
== "Error: Access denied. Please check your login status and try again.\n"
@@ -129,12 +128,11 @@ def test_authentication_error_caught_by_wrapper_func(
129128

130129
@patch("blueapi.client.rest.requests.Session.request")
131130
def test_remote_error_raised_by_wrapper_func(mock_requests: Mock, runner: CliRunner):
132-
mock_requests.side_effect = BlueskyRemoteControlError("Response [450]")
133-
131+
mock_requests.side_effect = BlueskyRemoteControlError(message="Response [450]")
134132
result = runner.invoke(main, ["controller", "plans"])
135133
assert (
136134
isinstance(result.exception, BlueskyRemoteControlError)
137-
and result.exception.args == ("Response [450]",)
135+
and result.exception.args[1] == "Response [450]"
138136
and result.exit_code == 1
139137
)
140138

@@ -680,7 +678,7 @@ def test_env_reload_server_side_error(runner: CliRunner):
680678
assert isinstance(result.exception, BlueskyRemoteControlError), (
681679
"Expected a BlueskyRemoteError from cli runner"
682680
)
683-
assert result.exception.args[0] == "Failed to tear down the environment"
681+
assert result.exception.args[1] == "Failed to tear down the environment"
684682

685683
# Check if the endpoints were hit as expected
686684
assert len(responses.calls) == 1 # +1 for the DELETE call
@@ -716,20 +714,25 @@ def test_env_reload_server_side_error(runner: CliRunner):
716714
"Error: Incorrect parameters supplied\n Missing value for 'foo'\n",
717715
),
718716
(
719-
BlueskyRemoteControlError("Server error"),
720-
"Error: server error with this message: Server error\n",
717+
BlueskyRemoteControlError(message="Server error"),
718+
"Error: remote control error: Server error\n",
721719
),
722720
(
723721
ValueError("Error parsing parameters"),
724722
"Error: task could not run: Error parsing parameters\n",
725723
),
724+
(
725+
BlueskyStreamingError("streaming failed"),
726+
"Error: streaming error: streaming failed\n",
727+
),
726728
],
727729
ids=[
728730
"unknown_plan",
729731
"unauthorised_access",
730732
"invalid_parameters",
731733
"remote_control",
732734
"value_error",
735+
"streaming_error",
733736
],
734737
)
735738
def test_error_handling(exception, error_message, runner: CliRunner):

tests/unit_tests/client/test_client.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@
1919
PlanCache,
2020
)
2121
from blueapi.client.event_bus import AnyEvent, EventBusClient
22-
from blueapi.client.rest import BlueapiRestClient, BlueskyRemoteControlError
22+
from blueapi.client.rest import (
23+
BlueapiRestClient,
24+
BlueskyRemoteControlError,
25+
NotFoundError,
26+
)
2327
from blueapi.config import MissingStompConfigurationError
2428
from blueapi.core import DataEvent
2529
from blueapi.service.model import (
@@ -98,7 +102,14 @@ def mock_rest() -> BlueapiRestClient:
98102
mock.get_plans.return_value = PLANS
99103
mock.get_plan.side_effect = lambda n: {p.name: p for p in PLANS.plans}[n]
100104
mock.get_devices.return_value = DEVICES
101-
mock.get_device.side_effect = lambda n: {d.name: d for d in DEVICES.devices}[n]
105+
device_map = {d.name: d for d in DEVICES.devices}
106+
107+
def get_device(n: str):
108+
if n not in device_map:
109+
raise NotFoundError(404, "<Response [404]>")
110+
return device_map[n]
111+
112+
mock.get_device.side_effect = get_device
102113
mock.get_state.return_value = WorkerState.IDLE
103114
mock.get_task.return_value = TASK
104115
mock.get_all_tasks.return_value = TASKS
@@ -214,7 +225,7 @@ def test_create_and_start_task_fails_if_task_creation_fails(
214225
client: BlueapiClient,
215226
mock_rest: Mock,
216227
):
217-
mock_rest.create_task.side_effect = BlueskyRemoteControlError("No can do")
228+
mock_rest.create_task.side_effect = BlueskyRemoteControlError(message="No can do")
218229
with pytest.raises(BlueskyRemoteControlError):
219230
client.create_and_start_task(
220231
TaskRequest(name="baz", instrument_session="cm12345-1")
@@ -238,7 +249,9 @@ def test_create_and_start_task_fails_if_task_start_fails(
238249
mock_rest: Mock,
239250
):
240251
mock_rest.create_task.return_value = TaskResponse(task_id="baz")
241-
mock_rest.update_worker_task.side_effect = BlueskyRemoteControlError("No can do")
252+
mock_rest.update_worker_task.side_effect = BlueskyRemoteControlError(
253+
message="No can do"
254+
)
242255
with pytest.raises(BlueskyRemoteControlError):
243256
client.create_and_start_task(
244257
TaskRequest(name="baz", instrument_session="cm12345-1")

tests/unit_tests/client/test_rest.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
BlueskyRemoteControlError,
1212
BlueskyRequestError,
1313
InvalidParametersError,
14+
NotFoundError,
1415
ParameterError,
1516
UnauthorisedAccessError,
1617
UnknownPlanError,
@@ -39,8 +40,9 @@ def rest_with_auth(oidc_config: OIDCConfig, tmp_path) -> BlueapiRestClient:
3940
@pytest.mark.parametrize(
4041
"code,expected_exception",
4142
[
42-
(404, KeyError),
43-
(401, BlueskyRemoteControlError),
43+
(404, NotFoundError),
44+
(401, UnauthorisedAccessError),
45+
(403, UnauthorisedAccessError),
4446
(450, BlueskyRemoteControlError),
4547
(500, BlueskyRemoteControlError),
4648
],
@@ -63,9 +65,9 @@ def test_rest_error_code(
6365
"code,content,expected_exception",
6466
[
6567
(200, None, None),
66-
(401, None, UnauthorisedAccessError()),
67-
(403, None, UnauthorisedAccessError()),
68-
(404, None, UnknownPlanError()),
68+
(401, None, UnauthorisedAccessError(401, "")),
69+
(403, None, UnauthorisedAccessError(403, "")),
70+
(404, None, UnknownPlanError(404, "")),
6971
(
7072
422,
7173
"""{
@@ -87,6 +89,11 @@ def test_rest_error_code(
8789
]
8890
),
8991
),
92+
(
93+
422,
94+
'{"detail": "not a list"}',
95+
BlueskyRequestError(422, ""),
96+
),
9097
(450, "non-standard", BlueskyRequestError(450, "non-standard")),
9198
(500, "internal_error", BlueskyRequestError(500, "internal_error")),
9299
],
@@ -102,8 +109,11 @@ def test_create_task_exceptions(
102109
response.json.side_effect = lambda: json.loads(content) if content else None
103110
err = _create_task_exceptions(response)
104111
assert isinstance(err, type(expected_exception))
105-
if expected_exception is not None:
106-
assert err.args == expected_exception.args
112+
if isinstance(expected_exception, InvalidParametersError):
113+
assert isinstance(err, InvalidParametersError)
114+
assert err.errors == expected_exception.errors
115+
elif expected_exception is not None:
116+
assert err.args[0] == code
107117

108118

109119
def test_auth_request_functionality(

0 commit comments

Comments
 (0)