Skip to content

Commit

Permalink
Add some tests
Browse files Browse the repository at this point in the history
  • Loading branch information
GDYendell committed Aug 8, 2024
1 parent 8634d4f commit 29b552f
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 4 deletions.
9 changes: 9 additions & 0 deletions tests/backends/epics/test_gui.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pvi.device import (
LED,
ButtonPanel,
ComboBox,
SignalR,
Expand Down Expand Up @@ -28,6 +29,7 @@ def test_get_components(mapping):

components = gui.extract_mapping_components(mapping.get_controller_mappings()[0])
assert components == [
SignalR(name="ReadBool", read_pv="DEVICE:ReadBool", read_widget=LED()),
SignalR(
name="ReadInt",
read_pv="DEVICE:ReadInt",
Expand All @@ -40,6 +42,13 @@ def test_get_components(mapping):
read_pv="DEVICE:ReadWriteFloat_RBV",
read_widget=TextRead(),
),
SignalRW(
name="ReadWriteInt",
write_pv="DEVICE:ReadWriteInt",
write_widget=TextWrite(),
read_pv="DEVICE:ReadWriteInt_RBV",
read_widget=TextRead(),
),
SignalRW(
name="StringEnum",
read_pv="DEVICE:StringEnum_RBV",
Expand Down
31 changes: 31 additions & 0 deletions tests/backends/epics/test_ioc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from pytest_mock import MockerFixture

from fastcs.backends.epics.ioc import EpicsIOC
from fastcs.mapping import Mapping


def test_ioc(mocker: MockerFixture, mapping: Mapping):
builder_mock = mocker.patch("fastcs.backends.epics.ioc.builder")

EpicsIOC("DEVICE", mapping)

builder_mock.aIn.assert_called_once_with("ReadWriteFloat_RBV", PREC=2)
builder_mock.aOut.assert_any_call(
"ReadWriteFloat", always_update=True, on_update=mocker.ANY, PREC=2
)
builder_mock.boolIn.assert_called_once_with("ReadBool", ZNAM="OFF", ONAM="ON")
builder_mock.boolOut.assert_called_once_with(
"WriteBool", ZNAM="OFF", ONAM="ON", always_update=True, on_update=mocker.ANY
)
builder_mock.longIn.assert_any_call("ReadInt")
builder_mock.longIn.assert_any_call("ReadWriteInt_RBV")
builder_mock.longOut.assert_called_with(
"ReadWriteInt", always_update=True, on_update=mocker.ANY
)
builder_mock.longStringIn.assert_called_once_with("StringEnum_RBV")
builder_mock.longStringOut.assert_called_once_with(
"StringEnum", always_update=True, on_update=mocker.ANY
)
builder_mock.aOut.assert_any_call(
"Go", initial_value=0, always_update=True, on_update=mocker.ANY
)
2 changes: 2 additions & 0 deletions tests/backends/tango/test_dsr.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ def test_collect_attributes(mapping):

# Check that attributes are created and of expected type
assert list(attributes.keys()) == [
"ReadBool",
"ReadInt",
"ReadWriteFloat",
"ReadWriteInt",
"StringEnum",
"WriteBool",
]
Expand Down
40 changes: 36 additions & 4 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import pytest

from fastcs.attributes import AttrR, AttrRW, AttrW
from fastcs.attributes import AttrR, AttrRW, AttrW, Handler, Sender, Updater
from fastcs.controller import Controller
from fastcs.datatypes import Bool, Float, Int, String
from fastcs.mapping import Mapping
from fastcs.wrappers import command
from fastcs.wrappers import command, scan

# Prevent pytest from catching exceptions when debugging in vscode so that break on
# exception works correctly (see: https://github.com/pytest-dev/pytest/issues/7409)
Expand All @@ -21,16 +21,48 @@ def pytest_internalerror(excinfo):
raise excinfo.value


class TestUpdater(Updater):
update_period = 1

async def update(self, controller, attr):
print(f"{controller} update {attr}")


class TestSender(Sender):
async def put(self, controller, attr, value):
print(f"{controller}: {attr} = {value}")


class TestHandler(Handler, TestUpdater, TestSender):
pass


class TestController(Controller):
read_int: AttrR = AttrR(Int())
read_int: AttrR = AttrR(Int(), handler=TestUpdater())
read_write_int: AttrRW = AttrRW(Int(), handler=TestHandler())
read_write_float: AttrRW = AttrRW(Float())
write_bool: AttrW = AttrW(Bool())
read_bool: AttrR = AttrR(Bool())
write_bool: AttrW = AttrW(Bool(), handler=TestSender())
string_enum: AttrRW = AttrRW(String(), allowed_values=["red", "green", "blue"])

initialised = False
connected = False
count = 0

async def initialise(self) -> None:
self.initialised = True

async def connect(self) -> None:
self.connected = True

@command()
async def go(self):
pass

@scan(0.01)
async def counter(self):
self.count += 1


@pytest.fixture
def controller():
Expand Down
33 changes: 33 additions & 0 deletions tests/test_attribute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from functools import partial

import pytest

from fastcs.attributes import AttrR, AttrRW
from fastcs.datatypes import Int, String


@pytest.mark.asyncio
async def test_attributes():
device = {"state": "Idle", "number": 1, "count": False}
ui = {"state": "", "number": 0, "count": False}

async def update_ui(value, key):
ui[key] = value

async def send(value, key):
device[key] = value

async def device_add():
device["number"] += 1

attr_r = AttrR(String())
attr_r.set_update_callback(partial(update_ui, key="state"))
await attr_r.set(device["state"])
assert ui["state"] == "Idle"

attr_rw = AttrRW(Int())
attr_rw.set_process_callback(partial(send, key="number"))
attr_rw.set_write_display_callback(partial(update_ui, key="number"))
await attr_rw.process(2)
assert device["number"] == 2
assert ui["number"] == 2
45 changes: 45 additions & 0 deletions tests/test_backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from time import sleep

import pytest

from fastcs.backend import Backend


class DummyBackend(Backend):
def __init__(self, controller):
super().__init__(controller)

self.init_task_called = False
self._initial_tasks.append(self.init_task)

async def init_task(self):
self.init_task_called = True

def _run(self):
pass


@pytest.mark.asyncio
async def test_backend(controller):
backend = DummyBackend(controller)

# Controller should be initialised by Backend, bit not connected
assert controller.initialised
assert not controller.connected

# Controller Attributes with a Sender should have a _process_callback created
assert controller.read_write_int.has_process_callback()

backend.run()

# Controller should have been connected by Backend
assert controller.connected

# Initial tasks should be complete
assert backend.init_task_called

# Scan tasks should be running
for _ in range(3):
count = controller.count
sleep(0.05)
assert controller.count > count

0 comments on commit 29b552f

Please sign in to comment.