Skip to content

Commit de96ec9

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

File tree

2 files changed

+84
-2
lines changed

2 files changed

+84
-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: 83 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,78 @@ 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(builder._write_directory.joinpath("config/devsta.db")),
136+
"w",
137+
)
138+
mock_print.assert_called_once()
139+
140+
# Make sure the record is deleted
141+
ClearRecords()
142+
143+
70144
def test_missing_service(builder, caplog):
71145
builder._extract_entities = Mock(side_effect=OSError())
72146
builder._extract_services()
@@ -134,16 +208,22 @@ def test_builder_validate_screen(builder_with_setup):
134208

135209

136210
def test_create_screens(builder_with_setup):
211+
# We don't want to make a devsta PV in this test
212+
builder_with_setup._create_devsta_pv = Mock()
137213
# We don't want to access Generator in this test
138214
builder_with_setup._generate_screen = Mock()
139215
builder_with_setup._validate_screen = Mock()
216+
140217
builder_with_setup.create_screens()
141218

142219
builder_with_setup._generate_screen.assert_called()
143220
# builder_with_setup._validate_screen.assert_called()
144221

145222

146223
def test_create_screens_no_entities(builder, caplog):
224+
# We don't want to make a devsta PV in this test
225+
builder._create_devsta_pv = Mock()
226+
147227
builder.entities = []
148228

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

157237

158238
def test_create_screens_extra_p_does_not_exist(builder_with_setup, caplog):
239+
# We don't want to make a devsta PV in this test
240+
builder_with_setup._create_devsta_pv = Mock()
159241
# We don't want to actually generate a screen
160242
builder_with_setup._generate_screen = Mock(side_effect=None)
161243

0 commit comments

Comments
 (0)