From 197641d92f27ebd079d3f4c270c4e70e2f69925c Mon Sep 17 00:00:00 2001 From: Brian Koopman Date: Tue, 12 Dec 2023 14:45:51 -0500 Subject: [PATCH 01/10] Drop integration test This is falling behind and not really adding anything on top of testing components individually at the moment. --- tests/integration/test_example_script.py | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 tests/integration/test_example_script.py diff --git a/tests/integration/test_example_script.py b/tests/integration/test_example_script.py deleted file mode 100644 index bb9680d..0000000 --- a/tests/integration/test_example_script.py +++ /dev/null @@ -1,23 +0,0 @@ -import datetime as dt -from unittest.mock import MagicMock, patch - -from util import mocked_clients - -from sorunlib import * - - -# patch out time.sleep so we don't actually wait during testing -@patch('sorunlib.commands.time.sleep', MagicMock()) -@patch('sorunlib.create_clients', mocked_clients) -def test_script(): - initialize() - # wait until 1 second in future - wait_until((dt.datetime.utcnow() + dt.timedelta(seconds=1)).isoformat()) - acu.move_to(39.39, 64.27) - smurf.iv_curve() - smurf.bias_step() - # wait until 1 second in future - wait_until((dt.datetime.utcnow() + dt.timedelta(seconds=1)).isoformat()) - seq.scan(description='test', stop_time=(dt.datetime.utcnow() - + dt.timedelta(seconds=1)).isoformat(), width=20.) - smurf.bias_step() From dec0f7fedb22c7615c9fbacde79ca52550d17d35 Mon Sep 17 00:00:00 2001 From: Brian Koopman Date: Tue, 12 Dec 2023 14:38:44 -0500 Subject: [PATCH 02/10] Move acu client creation to util Also use pytest-mock based fixture in acu testing. This moves us closer to consolidating the mock client creation across all testing module. --- tests/test_acu.py | 64 +++++++++++------------------------------------ tests/util.py | 34 ++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/tests/test_acu.py b/tests/test_acu.py index 623030c..defe715 100644 --- a/tests/test_acu.py +++ b/tests/test_acu.py @@ -3,74 +3,40 @@ import pytest -from unittest.mock import MagicMock, patch - -import ocs from ocs.ocs_client import OCSReply from sorunlib import acu -from util import create_session - - -def create_acu_client(platform_type): - """Create an ACU client with mock monitor Process session.data. - - Args: - platform_type (str): Either 'satp' or 'ccat'. - - """ - acu_client = MagicMock() - session = create_session('monitor') - session.data = {'PlatformType': platform_type} - reply = OCSReply(ocs.OK, 'msg', session.encoded()) - acu_client.monitor.status = MagicMock(return_value=reply) - - return acu_client +from util import create_patch_clients -def mocked_clients(test_mode): - clients = {'acu': MagicMock(), - 'smurf': [MagicMock(), MagicMock(), MagicMock()]} +patch_clients_satp = create_patch_clients('satp') +patch_clients_lat = create_patch_clients('ccat') - return clients - -@patch('sorunlib.create_clients', mocked_clients) -def test_move_to(): - acu.run.initialize(test_mode=True) +def test_move_to(patch_clients_satp): acu.move_to(180, 60) acu.run.CLIENTS['acu'].go_to.assert_called_with(az=180, el=60) -@patch('sorunlib.create_clients', mocked_clients) -def test_set_boresight(): - acu.run.initialize(test_mode=True) - acu.run.CLIENTS['acu'] = create_acu_client('satp') +def test_move_to_failed(patch_clients_satp): + mocked_response = OCSReply( + 0, 'msg', {'success': False, 'op_name': 'go_to'}) + acu.run.CLIENTS['acu'].go_to.side_effect = [mocked_response] + with pytest.raises(RuntimeError): + acu.move_to(180, 90) + + +def test_set_boresight(patch_clients_satp): acu.set_boresight(20) acu.run.CLIENTS['acu'].set_boresight.assert_called_with(target=20) -@patch('sorunlib.create_clients', mocked_clients) -def test_set_boresight_lat(): - acu.run.initialize(test_mode=True) - acu.run.CLIENTS['acu'] = create_acu_client('ccat') +def test_set_boresight_lat(patch_clients_lat): with pytest.raises(RuntimeError): acu.set_boresight(20) -@patch('sorunlib.create_clients', mocked_clients) -def test_move_to_failed(): - acu.run.initialize() - mocked_response = OCSReply( - 0, 'msg', {'success': False, 'op_name': 'go_to'}) - acu.run.CLIENTS['acu'].go_to.side_effect = [mocked_response] - with pytest.raises(RuntimeError): - acu.move_to(180, 90) - - -@patch('sorunlib.create_clients', mocked_clients) -def test_set_scan_params(): - acu.run.initialize(test_mode=True) +def test_set_scan_params(patch_clients_satp): acu.set_scan_params(az_speed=2, az_accel=2, reset=True) acu.run.CLIENTS['acu'].set_scan_params.assert_called_with( az_speed=2, diff --git a/tests/util.py b/tests/util.py index 3a72c6c..223ca0b 100644 --- a/tests/util.py +++ b/tests/util.py @@ -1,6 +1,10 @@ +import pytest + from unittest.mock import MagicMock +import ocs from ocs.ocs_agent import OpSession +from ocs.ocs_client import OCSReply def create_session(op_name): @@ -35,11 +39,39 @@ def _mock_smurf_client(instance_id): return smurf +def _mock_acu_client(platform_type): + """Create an ACU client with mock monitor Process session.data.""" + acu_client = MagicMock() + session = create_session('monitor') + session.data = {'PlatformType': platform_type} + reply = OCSReply(ocs.OK, 'msg', session.encoded()) + acu_client.monitor.status = MagicMock(return_value=reply) + + return acu_client + + def mocked_clients(**kwargs): + platform_type = kwargs.get('platform_type', 'satp') + smurf_ids = ['smurf1', 'smurf2', 'smurf3'] smurfs = [_mock_smurf_client(id_) for id_ in smurf_ids] - clients = {'acu': MagicMock(), + clients = {'acu': _mock_acu_client(platform_type), 'smurf': smurfs} return clients + + +def create_patch_clients(platform_type): + """Create patch_clients fixture that patches out the global CLIENTS list + with a set of mocked clients using the ``pytest-mock`` plugin. + + Args: + platform_type (str): Either 'satp' or 'ccat'. + + """ + @pytest.fixture() + def patch_clients(mocker): + mocker.patch('sorunlib.CLIENTS', mocked_clients(platform_type=platform_type)) + + return patch_clients From 645b036024bc43c0ff8b28bcea716e776fdc5ca8 Mon Sep 17 00:00:00 2001 From: Brian Koopman Date: Tue, 12 Dec 2023 15:00:56 -0500 Subject: [PATCH 03/10] Enable autouse on clients fixture and use in smurf tests --- tests/test_smurf.py | 7 ++----- tests/util.py | 10 ++++++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/test_smurf.py b/tests/test_smurf.py index 88d9d03..e6718f6 100644 --- a/tests/test_smurf.py +++ b/tests/test_smurf.py @@ -8,16 +8,13 @@ from ocs.ocs_client import OCSReply from sorunlib import smurf -from util import mocked_clients +from util import create_patch_clients # Use pytest-mock plugin to patch CLIENTS on all tests -@pytest.fixture(autouse=True) -def patch_clients(mocker): - mocker.patch('sorunlib.smurf.run.CLIENTS', mocked_clients()) +patch_clients = create_patch_clients('satp', autouse=True) -@patch('sorunlib.create_clients', mocked_clients) def test_set_targets(): smurf.set_targets(['smurf1']) assert len(smurf.run.CLIENTS['smurf']) == 1 diff --git a/tests/util.py b/tests/util.py index 223ca0b..f1301d0 100644 --- a/tests/util.py +++ b/tests/util.py @@ -62,15 +62,21 @@ def mocked_clients(**kwargs): return clients -def create_patch_clients(platform_type): +def create_patch_clients(platform_type, autouse=False): """Create patch_clients fixture that patches out the global CLIENTS list with a set of mocked clients using the ``pytest-mock`` plugin. Args: platform_type (str): Either 'satp' or 'ccat'. + autouse (bool): Whether to enable 'autouse' on the fixture. This will + enable the fixture for all tests within a test module. + + Returns: + function: A pytest fixture that patches out ``sorunlib.CLIENTS`` with a + set of mocked clients. """ - @pytest.fixture() + @pytest.fixture(autouse=autouse) def patch_clients(mocker): mocker.patch('sorunlib.CLIENTS', mocked_clients(platform_type=platform_type)) From df447a5fddc6e5471d3007b8b526711635613ab5 Mon Sep 17 00:00:00 2001 From: Brian Koopman Date: Wed, 13 Dec 2023 18:14:37 -0500 Subject: [PATCH 04/10] Move create_session from test__internal to util --- tests/test__internal.py | 15 ++++----------- tests/util.py | 6 +++++- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/tests/test__internal.py b/tests/test__internal.py index bbc16a3..9f1c44e 100644 --- a/tests/test__internal.py +++ b/tests/test__internal.py @@ -2,24 +2,17 @@ import ocs import pytest -from unittest.mock import MagicMock -from ocs.ocs_agent import OpSession from ocs.ocs_client import OCSReply from sorunlib._internal import check_response, check_running -os.environ["OCS_CONFIG_DIR"] = "./test_util/" +from util import create_session as create_unencoded_session +os.environ["OCS_CONFIG_DIR"] = "./test_util/" -def create_session(op_name, status=None, success=None): - """Create an OpSession with a mocked app for testing.""" - mock_app = MagicMock() - session = OpSession(1, op_name, app=mock_app) - session.op_name = 'test_op' - if status is not None: - session.set_status(status) - session.success = success +def create_session(*args, **kwargs): + session = create_unencoded_session(*args, **kwargs) return session.encoded() diff --git a/tests/util.py b/tests/util.py index f1301d0..57b6000 100644 --- a/tests/util.py +++ b/tests/util.py @@ -7,10 +7,14 @@ from ocs.ocs_client import OCSReply -def create_session(op_name): +def create_session(op_name, status=None, success=None): """Create an OpSession with a mocked app for testing.""" mock_app = MagicMock() session = OpSession(1, op_name, app=mock_app) + session.op_name = 'test_op' + if status is not None: + session.set_status(status) + session.success = success return session From b94ff18558de39be0f2ef63afd5ae85ceb6ac286 Mon Sep 17 00:00:00 2001 From: Brian Koopman Date: Mon, 18 Dec 2023 15:08:15 -0500 Subject: [PATCH 05/10] Use patch clients fixture in a wiregrid test --- tests/test_wiregrid.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_wiregrid.py b/tests/test_wiregrid.py index d238fab..f6f4091 100644 --- a/tests/test_wiregrid.py +++ b/tests/test_wiregrid.py @@ -10,7 +10,9 @@ from ocs.ocs_client import OCSReply from sorunlib import wiregrid -from util import create_session +from util import create_session, create_patch_clients + +patch_clients = create_patch_clients('satp') def create_acu_client(az, el, boresight): @@ -193,9 +195,7 @@ def test__check_temperature_sensors(): wiregrid.run.CLIENTS['wiregrid']['labjack'].acq.status.assert_called_once() -@patch('sorunlib.wiregrid.run.CLIENTS', mocked_clients()) -def test__check_telescope_position(): - wiregrid.run.CLIENTS['acu'] = create_acu_client(180, 50, 0) +def test__check_telescope_position(patch_clients): wiregrid._check_telescope_position() wiregrid.run.CLIENTS['acu'].monitor.status.assert_called_once() From f105305fab3a371d1c031a61aa228ee3af87bef2 Mon Sep 17 00:00:00 2001 From: Brian Koopman Date: Fri, 15 Dec 2023 10:27:44 -0500 Subject: [PATCH 06/10] Add wiregrid clients to util mocked_clients --- tests/test_wiregrid.py | 13 +------------ tests/util.py | 6 +++++- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/tests/test_wiregrid.py b/tests/test_wiregrid.py index f6f4091..d4795bf 100644 --- a/tests/test_wiregrid.py +++ b/tests/test_wiregrid.py @@ -10,7 +10,7 @@ from ocs.ocs_client import OCSReply from sorunlib import wiregrid -from util import create_session, create_patch_clients +from util import create_session, create_patch_clients, mocked_clients patch_clients = create_patch_clients('satp') @@ -113,17 +113,6 @@ def create_encoder_client(): return client -def mocked_clients(): - clients = {'acu': MagicMock(), - 'smurf': [MagicMock(), MagicMock(), MagicMock()], - 'wiregrid': {'actuator': MagicMock(), - 'encoder': MagicMock(), - 'kikusui': MagicMock(), - 'labjack': MagicMock()}} - - return clients - - @patch('sorunlib.wiregrid.run.CLIENTS', mocked_clients()) def test_insert(): wiregrid.insert() diff --git a/tests/util.py b/tests/util.py index 57b6000..bdc1dc2 100644 --- a/tests/util.py +++ b/tests/util.py @@ -61,7 +61,11 @@ def mocked_clients(**kwargs): smurfs = [_mock_smurf_client(id_) for id_ in smurf_ids] clients = {'acu': _mock_acu_client(platform_type), - 'smurf': smurfs} + 'smurf': smurfs, + 'wiregrid': {'actuator': MagicMock(), + 'encoder': MagicMock(), + 'kikusui': MagicMock(), + 'labjack': MagicMock()}} return clients From 429fa73b32b5c6c078a51e4cca792d10ecb23e3f Mon Sep 17 00:00:00 2001 From: Brian Koopman Date: Fri, 15 Dec 2023 10:28:14 -0500 Subject: [PATCH 07/10] Use util mocked_clients in failing wiregrid test --- tests/test_wiregrid.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_wiregrid.py b/tests/test_wiregrid.py index d4795bf..3c4dd41 100644 --- a/tests/test_wiregrid.py +++ b/tests/test_wiregrid.py @@ -233,9 +233,8 @@ def test__check_agents_online(): @pytest.mark.parametrize('continuous', [(True), (False)]) -@patch('sorunlib.wiregrid.run.CLIENTS', mocked_clients()) @patch('sorunlib.wiregrid.time.sleep', MagicMock()) -def test_calibrate_stepwise(continuous): +def test_calibrate_stepwise(patch_clients, continuous): # Setup all mock clients wiregrid.run.CLIENTS['acu'] = create_acu_client(180, 50, 0) wiregrid.run.CLIENTS['wiregrid']['actuator'] = create_actuator_client(motor=1) From a663bfbf8852e990a291a3f436e307b24314a3f8 Mon Sep 17 00:00:00 2001 From: Brian Koopman Date: Mon, 18 Dec 2023 12:08:41 -0500 Subject: [PATCH 08/10] Use patch clients fixture in test_seq.py --- tests/test_seq.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tests/test_seq.py b/tests/test_seq.py index 5d766da..e47ad4d 100644 --- a/tests/test_seq.py +++ b/tests/test_seq.py @@ -1,5 +1,6 @@ import os os.environ["OCS_CONFIG_DIR"] = "./test_util/" +os.environ["SORUNLIB_CONFIG"] = "./data/example_config.yaml" import datetime as dt import pytest @@ -8,27 +9,20 @@ import sorunlib from sorunlib import seq +from util import create_patch_clients -def mocked_clients(test_mode): - clients = {'acu': MagicMock(), - 'smurf': [MagicMock(), MagicMock(), MagicMock()]} - return clients +patch_clients = create_patch_clients('satp') -@patch('sorunlib.create_clients', mocked_clients) @patch('sorunlib.commands.time.sleep', MagicMock()) -def test_scan(): - seq.run.initialize(test_mode=True) +def test_scan(patch_clients): target = dt.datetime.now() + dt.timedelta(seconds=1) seq.scan(description='test', stop_time=target.isoformat(), width=20.) -@patch('sorunlib.create_clients', mocked_clients) @patch('sorunlib.commands.time.sleep', MagicMock()) -def test_scan_failed_to_start(): - seq.run.initialize(test_mode=True) - +def test_scan_failed_to_start(patch_clients): # Setup mock OCSReply without session object mock_reply = MagicMock() mock_reply.session = None From 77b6c50184ffd1bbb0c9b5eb8729f4a93eb393e2 Mon Sep 17 00:00:00 2001 From: Brian Koopman Date: Mon, 18 Dec 2023 12:07:47 -0500 Subject: [PATCH 09/10] Add default position and generate_scan responses --- tests/util.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/util.py b/tests/util.py index bdc1dc2..c1dde37 100644 --- a/tests/util.py +++ b/tests/util.py @@ -43,15 +43,23 @@ def _mock_smurf_client(instance_id): return smurf -def _mock_acu_client(platform_type): +def _mock_acu_client(platform_type, az=180, el=50, boresight=0): """Create an ACU client with mock monitor Process session.data.""" - acu_client = MagicMock() + acu = MagicMock() session = create_session('monitor') - session.data = {'PlatformType': platform_type} + session.data = {'PlatformType': platform_type, + 'StatusDetailed': {'Azimuth current position': az, + 'Elevation current position': el, + 'Boresight current position': boresight}} reply = OCSReply(ocs.OK, 'msg', session.encoded()) - acu_client.monitor.status = MagicMock(return_value=reply) + acu.monitor.status = MagicMock(return_value=reply) - return acu_client + session = create_session('generate_scan', status='running') + reply = OCSReply(ocs.OK, 'msg', session.encoded()) + acu.generate_scan.start = MagicMock(return_value=reply) + acu.generate_scan.status = MagicMock(return_value=reply) + + return acu def mocked_clients(**kwargs): From a4684c6e073e474d190e23f8389c43bd861fd9d2 Mon Sep 17 00:00:00 2001 From: Brian Koopman Date: Mon, 18 Dec 2023 18:13:49 -0500 Subject: [PATCH 10/10] Create test for initialize function --- tests/test_sorunlib.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/test_sorunlib.py diff --git a/tests/test_sorunlib.py b/tests/test_sorunlib.py new file mode 100644 index 0000000..e1306cf --- /dev/null +++ b/tests/test_sorunlib.py @@ -0,0 +1,13 @@ +from unittest.mock import MagicMock, patch + +from util import mocked_clients + +import sorunlib +from sorunlib import initialize + + +@patch('sorunlib.commands.time.sleep', MagicMock()) +@patch('sorunlib.create_clients', mocked_clients) +def test_initialize(): + initialize() + assert sorunlib.CLIENTS is not None