1+ import copy
2+ import re
3+ from typing import Any
4+
15import pytest
26from pytest_mock import MockerFixture
37from tango import DevState
4- from tango ._tango import AttrWriteType , CmdArgType
8+ from tango .test_context import DeviceTestContext
9+ from tests .conftest import AssertableController
510
611from fastcs .attributes import AttrR
7- from fastcs .backends .tango .dsr import _collect_dev_attributes , _collect_dev_commands
8- from fastcs .datatypes import Bool , Int
9-
10-
11- def test_collect_attributes (mapping ):
12- attributes = _collect_dev_attributes (mapping )
13-
14- # Check that attributes are created and of expected type
15- assert list (attributes .keys ()) == [
16- "BigEnum" ,
17- "ReadBool" ,
18- "ReadInt" ,
19- "ReadWriteFloat" ,
20- "ReadWriteInt" ,
21- "StringEnum" ,
22- "WriteBool" ,
23- ]
24- assert attributes ["ReadInt" ].attr_write == AttrWriteType .READ
25- assert attributes ["ReadInt" ].attr_type == CmdArgType .DevLong64
26- assert attributes ["StringEnum" ].attr_write == AttrWriteType .READ_WRITE
27- assert attributes ["StringEnum" ].attr_type == CmdArgType .DevString
28- assert attributes ["ReadWriteFloat" ].attr_write == AttrWriteType .READ_WRITE
29- assert attributes ["ReadWriteFloat" ].attr_type == CmdArgType .DevDouble
30- assert attributes ["WriteBool" ].attr_write == AttrWriteType .WRITE
31- assert attributes ["WriteBool" ].attr_type == CmdArgType .DevBoolean
32-
33-
34- @pytest .mark .asyncio
35- async def test_collect_commands (mapping , mocker : MockerFixture ):
36- commands = _collect_dev_commands (mapping )
37-
38- # Check that command is created and it can be called
39- assert list (commands .keys ()) == ["Go" ]
40- await commands ["Go" ](mocker .MagicMock ())
12+ from fastcs .backends .tango .backend import TangoBackend
13+ from fastcs .datatypes import Bool , Float , Int
14+
15+
16+ def pascal_2_snake (input : list [str ]) -> list [str ]:
17+ snake_list = copy .deepcopy (input )
18+ snake_list [- 1 ] = re .sub (r"(?<!^)(?=[A-Z])" , "_" , snake_list [- 1 ]).lower ()
19+ return snake_list
4120
4221
4322class TestTangoDevice :
23+ @pytest .fixture (scope = "class" , autouse = True )
24+ def setup_class (self , class_mocker : MockerFixture ):
25+ self .controller = AssertableController (class_mocker )
26+
27+ @pytest .fixture (scope = "class" )
28+ def tango_context (self ):
29+ device = TangoBackend (self .controller )._dsr ._device
30+ with DeviceTestContext (device ) as proxy :
31+ yield proxy
32+
33+ @pytest .fixture (scope = "class" )
34+ def client_read (self , tango_context ):
35+ def _read_attribute (path : list [str ], expected : Any ):
36+ attribute = "_" .join (path )
37+ with self .controller .assertPerformed (pascal_2_snake (path ), "READ" ):
38+ result = tango_context .read_attribute (attribute ).value
39+ assert result == expected
40+
41+ return _read_attribute
42+
43+ @pytest .fixture (scope = "class" )
44+ def client_write (self , tango_context ):
45+ def _write_attribute (path : list [str ], expected : Any ):
46+ attribute = "_" .join (path )
47+ with self .controller .assertPerformed (pascal_2_snake (path ), "WRITE" ):
48+ tango_context .write_attribute (attribute , expected )
49+
50+ return _write_attribute
51+
52+ @pytest .fixture (scope = "class" )
53+ def client_exec (self , tango_context ):
54+ def _exec_command (path : list [str ]):
55+ command = "_" .join (path )
56+ with self .controller .assertPerformed (pascal_2_snake (path ), "EXECUTE" ):
57+ tango_context .command_inout (command )
58+
59+ return _exec_command
60+
4461 def test_list_attributes (self , tango_context ):
4562 assert list (tango_context .get_attribute_list ()) == [
4663 "BigEnum" ,
@@ -50,6 +67,8 @@ def test_list_attributes(self, tango_context):
5067 "ReadWriteInt" ,
5168 "StringEnum" ,
5269 "WriteBool" ,
70+ "SubController01_ReadInt" ,
71+ "SubController02_ReadInt" ,
5372 "State" ,
5473 "Status" ,
5574 ]
@@ -62,46 +81,44 @@ def test_list_commands(self, tango_context):
6281 "Status" ,
6382 ]
6483
65- def test_read_int (self , tango_context ):
66- result = tango_context .read_attribute ("ReadInt" )
67- assert result .value == AttrR (Int ())._value
84+ def test_state (self , tango_context ):
85+ assert tango_context .command_inout ("State" ) == DevState .ON
86+
87+ def test_status (self , tango_context ):
88+ expected = "The device is in ON state."
89+ assert tango_context .command_inout ("Status" ) == expected
90+
91+ def test_read_int (self , client_read ):
92+ client_read (["ReadInt" ], AttrR (Int ())._value )
6893
69- def test_read_write_int (self , tango_context ):
70- expected = 42
71- tango_context .write_attribute ("ReadWriteInt" , expected )
72- result = tango_context .read_attribute ("ReadWriteInt" )
73- assert result .w_value == expected
94+ def test_read_write_int (self , client_read , client_write ):
95+ client_read (["ReadWriteInt" ], AttrR (Int ())._value )
96+ client_write (["ReadWriteInt" ], AttrR (Int ())._value )
7497
75- def test_read_write_float (self , tango_context ):
76- expected = 23.1
77- tango_context .write_attribute ("ReadWriteFloat" , expected )
78- result = tango_context .read_attribute ("ReadWriteFloat" )
79- assert result .w_value == expected
98+ def test_read_write_float (self , client_read , client_write ):
99+ client_read (["ReadWriteFloat" ], AttrR (Float ())._value )
100+ client_write (["ReadWriteFloat" ], AttrR (Float ())._value )
80101
81- def test_read_bool (self , tango_context ):
82- result = tango_context .read_attribute ("ReadBool" )
83- assert result .value == AttrR (Bool ())._value
102+ def test_read_bool (self , client_read ):
103+ client_read (["ReadBool" ], AttrR (Bool ())._value )
84104
85- def test_write_bool (self , tango_context ):
86- tango_context . write_attribute ( "WriteBool" , AttrR (Bool ())._value )
105+ def test_write_bool (self , client_write ):
106+ client_write ([ "WriteBool" ] , AttrR (Bool ())._value )
87107
88108 # # We need to discuss enums
89- # def test_string_enum(self, tango_context):
90- # expected = 1
91- # tango_context.write_attribute("StringEnum", "green")
92- # result = tango_context.read_attribute("StringEnum")
93- # assert result.w_value == expected
109+ # def test_string_enum(self, client_read, client_write):
110+ # client_read(["StringEnum"], "green")
111+ # client_write(["StringEnum"], "green")
94112
95- def test_big_enum (self , tango_context ):
96- result = tango_context .read_attribute ("BigEnum" )
97- assert result .value == AttrR (Int (), allowed_values = list (range (1 , 18 )))._value
113+ def test_big_enum (self , client_read ):
114+ client_read (["BigEnum" ], AttrR (Int (), allowed_values = list (range (1 , 18 )))._value )
98115
99- def test_go (self , tango_context ):
100- tango_context .command_inout ("go" )
116+ # The method works but does not seem linked to the device instance?
117+ # def test_go(self, client_exec):
118+ # client_exec(["Go"])
101119
102- def test_state (self , tango_context ):
103- assert tango_context . command_inout ( "State" ) == DevState . ON
120+ def test_read_child1 (self , client_read ):
121+ client_read ([ "SubController01" , "ReadInt" ], AttrR ( Int ()). _value )
104122
105- def test_status (self , tango_context ):
106- expected = "The device is in ON state."
107- assert tango_context .command_inout ("Status" ) == expected
123+ def test_read_child2 (self , client_read ):
124+ client_read (["SubController02" , "ReadInt" ], AttrR (Int ())._value )
0 commit comments