Skip to content

Commit

Permalink
Merge pull request #44 from ZohebShaikh/training-rigs-system-test
Browse files Browse the repository at this point in the history
Training rigs system test
  • Loading branch information
ZohebShaikh authored Dec 19, 2024
2 parents e0051a4 + b9e983a commit 8c92bc6
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 12 deletions.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
("py:class", "htss_rig_bluesky.devices.SampleStage"),
("py:class", "SampleStage"),
("py:class", "htss_rig_bluesky.plans.detector.Roi"),
("py:class", "ophyd_async.epics.areadetector.aravis.AravisDetector"),
("py:class", "ophyd_async.epics.adaravis._aravis.AravisDetector"),
("py:class", "AravisDetector"),
("py:class", "NoneType"),
("py:class", "'str'"),
Expand Down
12 changes: 9 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ classifiers = [
description = "Bluesky playground environment for Diamond's htss rigs"
dependencies = [
"ophyd",
"ophyd-async==0.4.0",
"ophyd-async>=0.8.0",
"databroker[client]==2.0.0b17",
"matplotlib<3.8",
"dls-dodal",
Expand Down Expand Up @@ -50,6 +50,8 @@ dev = [
"sphinx-design",
"tox-direct",
"types-mock",
"blueapi>=0.7.0",
"pytest-env",
]

[project.scripts]
Expand Down Expand Up @@ -78,6 +80,9 @@ addopts = """
filterwarnings = "error"
# Doctest python code in docs, python code in src docstrings, test functions in tests
testpaths = "docs tests"
env= [
"BEAMLINE=",
]

[tool.coverage.run]
data_file = "/tmp/htss_rig_bluesky.coverage"
Expand All @@ -93,7 +98,7 @@ legacy_tox_ini = """
[tox]
skipsdist=True
[testenv:{pre-commit,type-checking,tests,docs}]
[testenv:{pre-commit,type-checking,tests,docs,system-test}]
# Don't create a virtualenv for the command, requires tox-direct plugin
direct = True
passenv = *
Expand All @@ -106,8 +111,9 @@ allowlist_externals =
commands =
pre-commit: pre-commit run --all-files --show-diff-on-failure {posargs}
type-checking: mypy src tests {posargs}
tests: pytest --cov=htss_rig_bluesky --cov-report term --cov-report xml:cov.xml {posargs}
tests: pytest tests/unit_tests --cov=htss_rig_bluesky --cov-report term --cov-report xml:cov.xml {posargs}
docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html
system-test: pytest tests/system_tests {posargs}
"""

[tool.ruff]
Expand Down
6 changes: 3 additions & 3 deletions src/htss_rig_bluesky/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
Device,
StaticPathProvider,
)
from ophyd_async.epics.areadetector.aravis import AravisDetector
from ophyd_async.epics.motion import Motor
from ophyd_async.epics.signal import epics_signal_rw
from ophyd_async.epics.adaravis import AravisDetector
from ophyd_async.epics.core import epics_signal_rw
from ophyd_async.epics.motor import Motor

from .names import pv_prefix

Expand Down
12 changes: 8 additions & 4 deletions src/htss_rig_bluesky/plans/calibration.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
from collections.abc import Generator

import bluesky.plan_stubs as bps
Expand Down Expand Up @@ -41,11 +42,14 @@ def scan_center(
Yields:
Plan
"""

x_range = abs(sample.x.high_limit_travel - sample.x.low_limit_travel)
limits = asyncio.gather(
sample.x.high_limit_travel.get_value(), sample.x.low_limit_travel.get_value()
)
high, low = limits.result()
x_range = abs(high - low)
limit_margin = x_range * 0.01
min_x = min_x or sample.x.low_limit_travel + limit_margin
max_x = max_x or sample.x.high_limit_travel - limit_margin
min_x = min_x or low + limit_margin
max_x = max_x or high - limit_margin

yield from bps.mv(
det.drv.num_images,
Expand Down
2 changes: 1 addition & 1 deletion src/htss_rig_bluesky/plans/detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from dataclasses import dataclass

import bluesky.plan_stubs as bps
from ophyd_async.epics.areadetector.aravis import AravisDetector
from ophyd_async.epics.adaravis import AravisDetector


@dataclass
Expand Down
Empty file added tests/system_tests/__init__.py
Empty file.
52 changes: 52 additions & 0 deletions tests/system_tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import pytest
from blueapi.client.client import BlueapiClient
from blueapi.config import ApplicationConfig, RestConfig, StompConfig
from blueapi.worker.task import Task
from bluesky_stomp.models import BasicAuthentication

from htss_rig_bluesky.names import BEAMLINE


@pytest.fixture
def task_definition() -> dict[str, Task]:
return {
"step_scan_plan": Task(
name="step_scan_plan",
params={"detectors": "det", "motor": "sample_stage.theta"},
),
"fly_and_collect_plan": Task(
name="fly_and_collect_plan",
params={"panda": "panda", "diff": "det"},
),
"log_scan_plan": Task(
name="log_scan_plan",
params={"detectors": "det", "motor": "sample_stage.x"},
),
}


@pytest.fixture
def config() -> ApplicationConfig:
if BEAMLINE == "p46":
return ApplicationConfig(
stomp=StompConfig(
host="172.23.168.198",
auth=BasicAuthentication(username="guest", password="guest"), # type: ignore
),
api=RestConfig(
host="p46-blueapi.diamond.ac.uk", port=443, protocol="https"
),
)
else:
return ApplicationConfig(
stomp=StompConfig(
host="localhost",
auth=BasicAuthentication(username="guest", password="guest"), # type: ignore
)
)


# This client will use authentication if a valid cached token is found
@pytest.fixture
def client(config: ApplicationConfig) -> BlueapiClient:
return BlueapiClient.from_config(config=config)
75 changes: 75 additions & 0 deletions tests/system_tests/test_plans.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import pytest
from blueapi.client.client import BlueapiClient
from blueapi.client.event_bus import AnyEvent
from blueapi.core.bluesky_types import DataEvent
from blueapi.worker.event import TaskStatus, WorkerEvent, WorkerState
from blueapi.worker.task import Task

# Please export BEAMLINE=pXX before running the tests or add it in pyproject.toml


def _check_all_events(all_events: list[AnyEvent]):
assert (
isinstance(all_events[0], WorkerEvent) and all_events[0].task_status is not None
)
task_id = all_events[0].task_status.task_id
# First event is WorkerEvent
assert all_events[0] == WorkerEvent(
state=WorkerState.RUNNING,
task_status=TaskStatus(
task_id=task_id,
task_complete=False,
task_failed=False,
),
)

assert all(
isinstance(event, DataEvent) for event in all_events[1:-2]
), "Middle elements must be DataEvents."

# Last 2 events are WorkerEvent
assert all_events[-2:] == [
WorkerEvent(
state=WorkerState.IDLE,
task_status=TaskStatus(
task_id=task_id,
task_complete=False,
task_failed=False,
),
),
WorkerEvent(
state=WorkerState.IDLE,
task_status=TaskStatus(
task_id=task_id,
task_complete=True,
task_failed=False,
),
),
]


@pytest.mark.parametrize("device", ["sample_stage", "panda", "det"])
def test_device_present(client: BlueapiClient, device: str):
assert client.get_device(device), f"{device} is not available"


@pytest.mark.parametrize(
"plan", ["step_scan_plan", "fly_and_collect_plan", "log_scan_plan"]
)
def test_spec_scan_task(
client: BlueapiClient,
task_definition: dict[str, Task],
plan: str,
):
assert client.get_plan(plan), f"In {plan} is available"

all_events: list[AnyEvent] = []

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

client.run_task(task_definition[plan], on_event=on_event)

_check_all_events(all_events)

assert client.get_state() is WorkerState.IDLE
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 8c92bc6

Please sign in to comment.