Skip to content

Commit 5ea139e

Browse files
committed
Add tests for devsta PV generation
Minor fix to builder
1 parent 731abe3 commit 5ea139e

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

src/techui_builder/builder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def _create_devsta_pv(self, prefix: str, inputs: list[str]):
126126
self.devsta_pvs[prefix] = devsta_pv
127127

128128
def write_devsta_pvs(self):
129-
conf_dir = self._write_directory.parent.joinpath("config")
129+
conf_dir = self._write_directory.joinpath("config")
130130

131131
# Create the config/ dir if it doesn't exist
132132
if not conf_dir.exists():

tests/test_builder.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import logging
22
import os
3+
from io import StringIO
34
from pathlib import Path
4-
from unittest.mock import Mock, patch
5+
from unittest.mock import Mock, mock_open, patch
56

67
import pytest
78
from lxml import objectify
89
from phoebusgen.widget import ActionButton, Group
10+
from softioc.builder import ClearRecords, records
911

1012
from techui_builder.builder import (
1113
JsonMap,
@@ -67,6 +69,80 @@ def test_component_attributes(
6769
assert component.extras == extras
6870

6971

72+
def test_builder_create_devsta_pv(builder):
73+
p = "BL01T-MO-MOTOR-01"
74+
inpa = "BL01T-MO-MOTOR-01:MOTOR1.MOVN"
75+
builder._create_devsta_pv(prefix=p, inputs=[inpa])
76+
77+
devsta_pv = """
78+
record(calc, "BL01T-MO-MOTOR-01:DEVSTA")
79+
{
80+
field(ACKT, "NO")
81+
field(CALC, "(A|B|C|D|E|F|G|H|I|J|K|L)>0?1:0")
82+
field(INPA, "BL01T-MO-MOTOR-01:MOTOR1.MOVN")
83+
field(INPB, "")
84+
field(INPC, "")
85+
field(INPD, "")
86+
field(INPE, "")
87+
field(INPF, "")
88+
field(INPG, "")
89+
field(INPH, "")
90+
field(INPI, "")
91+
field(INPJ, "")
92+
field(INPK, "")
93+
field(INPL, "")
94+
field(SCAN, "1 second")
95+
}
96+
"""
97+
98+
assert builder.devsta_pvs != {}
99+
100+
# Fake file-like object to "print" the record to
101+
auto_devsta_pv = StringIO()
102+
# Get the string representation of the record
103+
builder.devsta_pvs[p].Print(auto_devsta_pv)
104+
105+
assert auto_devsta_pv.getvalue() == devsta_pv
106+
107+
# Make sure the record is deleted
108+
ClearRecords()
109+
110+
111+
def test_builder_write_devsta_pvs(builder):
112+
# To mock the open() function used in _write_devsta_pvs
113+
m = mock_open()
114+
115+
p = "BL01T-MO-MOTOR-01"
116+
inpa = "BL01T-MO-MOTOR-01:MOTOR1.MOVN"
117+
devsta_pv = records.calc( # pyright: ignore[reportAttributeAccessIssue]
118+
f"{p}:DEVSTA",
119+
CALC="(A|B|C|D|E|F|G|H|I|J|K|L)>0?1:0",
120+
SCAN="1 second",
121+
ACKT="NO",
122+
INPA=inpa,
123+
)
124+
builder.devsta_pvs[p] = devsta_pv
125+
126+
# Mock the Print() function so we don't actually write a file
127+
with (
128+
patch("builtins.open", m),
129+
patch("techui_builder.builder.Record.Print") as mock_print,
130+
):
131+
builder.write_devsta_pvs()
132+
133+
# Check open() was called with the correct args
134+
m.assert_called_once_with(
135+
Path(
136+
"/workspaces/techui-builder/tests/t01-services/synoptic/config/devsta.db"
137+
),
138+
"w",
139+
)
140+
mock_print.assert_called_once()
141+
142+
# Make sure the record is deleted
143+
ClearRecords()
144+
145+
70146
def test_missing_service(builder, caplog):
71147
builder._extract_entities = Mock(side_effect=OSError())
72148
builder._extract_services()
@@ -134,16 +210,22 @@ def test_builder_validate_screen(builder_with_setup):
134210

135211

136212
def test_create_screens(builder_with_setup):
213+
# We don't want to make a devsta PV in this test
214+
builder_with_setup._create_devsta_pv = Mock()
137215
# We don't want to access Generator in this test
138216
builder_with_setup._generate_screen = Mock()
139217
builder_with_setup._validate_screen = Mock()
218+
140219
builder_with_setup.create_screens()
141220

142221
builder_with_setup._generate_screen.assert_called()
143222
# builder_with_setup._validate_screen.assert_called()
144223

145224

146225
def test_create_screens_no_entities(builder, caplog):
226+
# We don't want to make a devsta PV in this test
227+
builder._create_devsta_pv = Mock()
228+
147229
builder.entities = []
148230

149231
# We only wan't to capture CRITICAL output in this test
@@ -156,6 +238,8 @@ def test_create_screens_no_entities(builder, caplog):
156238

157239

158240
def test_create_screens_extra_p_does_not_exist(builder_with_setup, caplog):
241+
# We don't want to make a devsta PV in this test
242+
builder_with_setup._create_devsta_pv = Mock()
159243
# We don't want to actually generate a screen
160244
builder_with_setup._generate_screen = Mock(side_effect=None)
161245

0 commit comments

Comments
 (0)