From a26b9d32cf6f17e392a28efbfc4e0fc48e45ce22 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Wed, 25 Mar 2026 10:59:52 +0100 Subject: [PATCH 1/9] tests: add max_examples and reduce n_points_pws in verify_shape tests Add max_examples=10 to @settings for test_do1d_verify_shape, test_do2d_verify_shape, test_dond_0d_verify_shape, test_dond_1d_verify_shape, and test_dond_2d_verify_shape. Without max_examples, hypothesis defaults to 100 examples, each running a full measurement + DB write cycle. Also reduce n_points_pws max_value from 500 to 50 since these tests verify shapes, not data integrity at scale. Reduces each parametrized variant from ~16-18s to ~1.2s. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/dataset/dond/test_do1d.py | 8 ++++++-- tests/dataset/dond/test_do2d.py | 8 ++++++-- tests/dataset/dond/test_doNd.py | 24 ++++++++++++++++++------ 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/tests/dataset/dond/test_do1d.py b/tests/dataset/dond/test_do1d.py index 8bda8997d31c..2c19c4f43fc8 100644 --- a/tests/dataset/dond/test_do1d.py +++ b/tests/dataset/dond/test_do1d.py @@ -105,9 +105,13 @@ def test_do1d_output_data(_param, _param_set) -> None: ) @given( num_points=hst.integers(min_value=1, max_value=10), - n_points_pws=hst.integers(min_value=1, max_value=500), + n_points_pws=hst.integers(min_value=1, max_value=50), +) +@settings( + deadline=None, + max_examples=10, + suppress_health_check=(HealthCheck.function_scoped_fixture,), ) -@settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) def test_do1d_verify_shape( _param, _param_complex, diff --git a/tests/dataset/dond/test_do2d.py b/tests/dataset/dond/test_do2d.py index 5c9c4ad432c4..3f1d8578ef53 100644 --- a/tests/dataset/dond/test_do2d.py +++ b/tests/dataset/dond/test_do2d.py @@ -193,9 +193,13 @@ def test_do2d_output_data(_param, _param_complex, _param_set, _param_set_2) -> N @given( num_points_p1=hst.integers(min_value=1, max_value=5), num_points_p2=hst.integers(min_value=1, max_value=5), - n_points_pws=hst.integers(min_value=1, max_value=500), + n_points_pws=hst.integers(min_value=1, max_value=50), +) +@settings( + deadline=None, + max_examples=10, + suppress_health_check=(HealthCheck.function_scoped_fixture,), ) -@settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) def test_do2d_verify_shape( _param, _param_complex, diff --git a/tests/dataset/dond/test_doNd.py b/tests/dataset/dond/test_doNd.py index e07a044d79a6..98a1c50382c8 100644 --- a/tests/dataset/dond/test_doNd.py +++ b/tests/dataset/dond/test_doNd.py @@ -328,8 +328,12 @@ def test_dond_multi_datasets_meas_names_len_mismatch(_param, experiment) -> None "multiparamtype", [MultiSetPointParam, Multi2DSetPointParam, Multi2DSetPointParam2Sizes], ) -@given(n_points_pws=hst.integers(min_value=1, max_value=500)) -@settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) +@given(n_points_pws=hst.integers(min_value=1, max_value=50)) +@settings( + deadline=None, + max_examples=10, + suppress_health_check=(HealthCheck.function_scoped_fixture,), +) def test_dond_0d_verify_shape( _param, _param_complex, multiparamtype, dummyinstrument, n_points_pws ) -> None: @@ -478,9 +482,13 @@ def test_dond_1d_parameter_with_array_vals(_param_set) -> None: ) @given( num_points=hst.integers(min_value=1, max_value=5), - n_points_pws=hst.integers(min_value=1, max_value=500), + n_points_pws=hst.integers(min_value=1, max_value=50), +) +@settings( + deadline=None, + max_examples=10, + suppress_health_check=(HealthCheck.function_scoped_fixture,), ) -@settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) def test_dond_1d_verify_shape( _param, _param_complex, @@ -648,9 +656,13 @@ def test_dond_1d_output_type(_param, _param_complex, _param_set) -> None: @given( num_points_p1=hst.integers(min_value=1, max_value=5), num_points_p2=hst.integers(min_value=1, max_value=5), - n_points_pws=hst.integers(min_value=1, max_value=500), + n_points_pws=hst.integers(min_value=1, max_value=50), +) +@settings( + deadline=None, + max_examples=10, + suppress_health_check=(HealthCheck.function_scoped_fixture,), ) -@settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) def test_dond_2d_verify_shape( _param, _param_complex, From fdd90e9a48b01ccf9583bcad98f846a3441e830d Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Wed, 25 Mar 2026 11:00:05 +0100 Subject: [PATCH 2/9] tests: reduce hypothesis examples and parameter ranges in dataset tests - test_datasaver_2d: add max_examples=10, reduce n_points max 50 -> 15 - test_datasaver_unsized_arrays: reduce N max_value from 500 to 50 - test_cache_2d, test_cache_2d_shape: reduce max_examples from 10 to 5 These tests perform per-iteration DB flush + cache validation, making each hypothesis example expensive. Reducing examples and parameter ranges maintains coverage while cutting runtime significantly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../measurement/test_measurement_context_manager.py | 2 +- tests/dataset/measurement/test_shapes.py | 10 +++++++--- tests/dataset/test_data_set_cache.py | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/dataset/measurement/test_measurement_context_manager.py b/tests/dataset/measurement/test_measurement_context_manager.py index 4377b81148af..56ff166d8b8d 100644 --- a/tests/dataset/measurement/test_measurement_context_manager.py +++ b/tests/dataset/measurement/test_measurement_context_manager.py @@ -972,7 +972,7 @@ def test_datasaver_foul_input(bg_writing) -> None: @settings(max_examples=10, deadline=None) -@given(N=hst.integers(min_value=2, max_value=500)) +@given(N=hst.integers(min_value=2, max_value=50)) @pytest.mark.usefixtures("empty_temp_db") @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.parametrize("storage_type", ["numeric", "array"]) diff --git a/tests/dataset/measurement/test_shapes.py b/tests/dataset/measurement/test_shapes.py index fd9830ba6863..4e338fdfe0d2 100644 --- a/tests/dataset/measurement/test_shapes.py +++ b/tests/dataset/measurement/test_shapes.py @@ -65,10 +65,14 @@ def test_datasaver_1d( ) -@settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) +@settings( + deadline=None, + max_examples=10, + suppress_health_check=(HealthCheck.function_scoped_fixture,), +) @given( - n_points_1=hst.integers(min_value=1, max_value=50), - n_points_2=hst.integers(min_value=1, max_value=50), + n_points_1=hst.integers(min_value=1, max_value=15), + n_points_2=hst.integers(min_value=1, max_value=15), ) @example(n_points_1=5, n_points_2=10) def test_datasaver_2d( diff --git a/tests/dataset/test_data_set_cache.py b/tests/dataset/test_data_set_cache.py index 270887b7428d..673520c054f0 100644 --- a/tests/dataset/test_data_set_cache.py +++ b/tests/dataset/test_data_set_cache.py @@ -455,7 +455,7 @@ def test_cache_1d_every_other_point( @pytest.mark.parametrize("in_memory_cache", [True, False]) @settings( deadline=None, - max_examples=10, + max_examples=5, suppress_health_check=(HealthCheck.function_scoped_fixture,), ) @given( @@ -838,7 +838,7 @@ def test_cache_1d_shape( @pytest.mark.parametrize("cache_size", ["too_large", "correct", "too_small"]) @settings( deadline=None, - max_examples=10, + max_examples=5, suppress_health_check=(HealthCheck.function_scoped_fixture,), ) @given( From 21a951e97a078863886a364ca0cb0c017b68260c Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Wed, 25 Mar 2026 11:00:16 +0100 Subject: [PATCH 3/9] tests: mock time.time() in cryomagnetics timeout test The wait_while_ramping method has a hardcoded 20s stability_check_interval. The test was waiting the full 20s for the timeout to trigger. Mock time.time() to simulate 21s elapsing instantly, reducing runtime from ~20s to <1s. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/drivers/test_cryomagnetics_4g.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/drivers/test_cryomagnetics_4g.py b/tests/drivers/test_cryomagnetics_4g.py index 27597225eac1..7f513d73085d 100644 --- a/tests/drivers/test_cryomagnetics_4g.py +++ b/tests/drivers/test_cryomagnetics_4g.py @@ -122,10 +122,25 @@ def test_set_field_blocking(cryo_instrument): def test_wait_while_ramping_timeout(cryo_instrument): - # Simulate _get_field always returning a value far from the setpoint + # Simulate _get_field always returning a value far from the setpoint. + # Mock time.time() to simulate 21s passing, avoiding real 20s wait + # for stability_check_interval timeout. + call_count = 0 + + def mock_time(): + nonlocal call_count + call_count += 1 + # First call sets last_check_time, subsequent calls exceed the + # 20s stability_check_interval + return 0.0 if call_count <= 1 else 21.0 + with ( patch.object(cryo_instrument, "_get_field", return_value=0.0), patch.object(cryo_instrument, "_sleep"), + patch( + "qcodes.instrument_drivers.cryomagnetics._cryomagnetics4g.time.time", + side_effect=mock_time, + ), ): with pytest.raises(Cryomagnetics4GException, match=r"Timeout|stabilized"): cryo_instrument.wait_while_ramping(1.0, threshold=1e-4) From b1f806e7019b5ffc8756784a943fa1e263864bcc Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Wed, 25 Mar 2026 11:20:55 +0100 Subject: [PATCH 4/9] tests: add max_examples and reduce n_points_pws in do0d verify_shape Add max_examples=10 and reduce n_points_pws max_value from 1000 to 50. Without max_examples, hypothesis defaults to 100 examples each running a full do0d() measurement cycle with up to 1000-point setpoints. Reduces each parametrized variant from ~14-16s to ~1.2s. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/dataset/dond/test_do0d.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/dataset/dond/test_do0d.py b/tests/dataset/dond/test_do0d.py index 3916392f4506..f8065f2f3234 100644 --- a/tests/dataset/dond/test_do0d.py +++ b/tests/dataset/dond/test_do0d.py @@ -100,8 +100,12 @@ def test_do0d_output_data(_param) -> None: "multiparamtype", [MultiSetPointParam, Multi2DSetPointParam, Multi2DSetPointParam2Sizes], ) -@given(n_points_pws=hst.integers(min_value=1, max_value=1000)) -@settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) +@given(n_points_pws=hst.integers(min_value=1, max_value=50)) +@settings( + deadline=None, + max_examples=10, + suppress_health_check=(HealthCheck.function_scoped_fixture,), +) def test_do0d_verify_shape( _param, _param_complex, multiparamtype, dummyinstrument, n_points_pws ) -> None: From 616574d548089fb26d3639741d094fd05f13a06e Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Wed, 25 Mar 2026 11:21:08 +0100 Subject: [PATCH 5/9] tests: reduce hypothesis ranges in test_nested_measurement_array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce max_examples from 25 to 10, outer_len max from 100 to 20, and inner_len max from 1000 to 200. The worst case was 100 outer iterations × 1000-element arrays × 2 datasets × 25 examples, creating millions of array operations per test run. Reduces from ~17s to ~2s. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/dataset/test_nested_measurements.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/dataset/test_nested_measurements.py b/tests/dataset/test_nested_measurements.py index c4db84f97fd6..7824a60b9831 100644 --- a/tests/dataset/test_nested_measurements.py +++ b/tests/dataset/test_nested_measurements.py @@ -86,11 +86,11 @@ def test_nested_measurement(bg_writing) -> None: @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("bg_writing", [True, False]) -@settings(deadline=None, max_examples=25) +@settings(deadline=None, max_examples=10) @given( - outer_len=hst.integers(min_value=1, max_value=100), - inner_len1=hst.integers(min_value=1, max_value=1000), - inner_len2=hst.integers(min_value=1, max_value=1000), + outer_len=hst.integers(min_value=1, max_value=20), + inner_len1=hst.integers(min_value=1, max_value=200), + inner_len2=hst.integers(min_value=1, max_value=200), ) def test_nested_measurement_array( bg_writing, outer_len, inner_len1, inner_len2 From c3b5bf06d3a10ae60841d9aa24c17930980dba35 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Wed, 25 Mar 2026 11:21:27 +0100 Subject: [PATCH 6/9] tests: reduce hypothesis examples and ranges in dataset tests - test_datasaver_1d: add max_examples=10, reduce n_points max 100 -> 50 - test_datasaver_arrays_of_different_length: add max_examples=10 (was default 100) - test_datasaver_array_parameters_channel (2 files): reduce N max 500 -> 100 - test_datasaver_array_parameters_array: reduce N max 500 -> 100 - test_cache_1d: reduce max_examples from 10 to 5 (16 parametrize combos make this inherently expensive) All tests verify correctness of data shapes and storage, not performance at scale. Reduced ranges still provide good coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../measurement/test_measurement_context_manager.py | 6 +++--- tests/dataset/measurement/test_shapes.py | 8 ++++++-- tests/dataset/test__get_data_from_ds.py | 2 +- tests/dataset/test_data_set_cache.py | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/dataset/measurement/test_measurement_context_manager.py b/tests/dataset/measurement/test_measurement_context_manager.py index 56ff166d8b8d..c71988f040ac 100644 --- a/tests/dataset/measurement/test_measurement_context_manager.py +++ b/tests/dataset/measurement/test_measurement_context_manager.py @@ -1113,7 +1113,7 @@ def test_datasaver_arrayparams( deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,), ) -@given(N=hst.integers(min_value=5, max_value=500)) +@given(N=hst.integers(min_value=5, max_value=100)) @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @pytest.mark.usefixtures("experiment") @@ -1633,7 +1633,7 @@ def test_datasaver_parameter_with_setpoints_reg_but_missing( deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,), ) -@given(N=hst.integers(min_value=5, max_value=500)) +@given(N=hst.integers(min_value=5, max_value=100)) @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @pytest.mark.parametrize("bg_writing", [True, False]) @@ -2166,7 +2166,7 @@ def test_datasaver_2d_multi_parameters_array( @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.parametrize("storage_type", ["numeric", "array"]) -@settings(deadline=None) +@settings(deadline=None, max_examples=10) @given(Ns=hst.lists(hst.integers(2, 10), min_size=2, max_size=5)) def test_datasaver_arrays_of_different_length(storage_type, Ns, bg_writing) -> None: """ diff --git a/tests/dataset/measurement/test_shapes.py b/tests/dataset/measurement/test_shapes.py index 4e338fdfe0d2..b9504dd47ccd 100644 --- a/tests/dataset/measurement/test_shapes.py +++ b/tests/dataset/measurement/test_shapes.py @@ -11,9 +11,13 @@ from pytest import LogCaptureFixture -@given(n_points=hst.integers(min_value=1, max_value=100)) +@given(n_points=hst.integers(min_value=1, max_value=50)) @example(n_points=5) -@settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) +@settings( + deadline=None, + max_examples=10, + suppress_health_check=(HealthCheck.function_scoped_fixture,), +) def test_datasaver_1d( experiment, DAC, DMM, caplog: "LogCaptureFixture", n_points ) -> None: diff --git a/tests/dataset/test__get_data_from_ds.py b/tests/dataset/test__get_data_from_ds.py index 6440b2775b2a..23d40105323a 100644 --- a/tests/dataset/test__get_data_from_ds.py +++ b/tests/dataset/test__get_data_from_ds.py @@ -156,7 +156,7 @@ def test_datasaver_multidimarrayparameter_as_numeric( deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,), ) -@given(N=hst.integers(min_value=5, max_value=500)) +@given(N=hst.integers(min_value=5, max_value=100)) @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @pytest.mark.usefixtures("experiment") diff --git a/tests/dataset/test_data_set_cache.py b/tests/dataset/test_data_set_cache.py index 673520c054f0..486fd1b8415b 100644 --- a/tests/dataset/test_data_set_cache.py +++ b/tests/dataset/test_data_set_cache.py @@ -191,7 +191,7 @@ def test_cache_standalone( @pytest.mark.parametrize("in_memory_cache", [True, False]) @settings( deadline=None, - max_examples=10, + max_examples=5, suppress_health_check=(HealthCheck.function_scoped_fixture,), ) @given(n_points=hst.integers(min_value=1, max_value=11)) From 60c1bbc90f0db3693cb8bc05b27e3794b4accdd4 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 26 Mar 2026 09:33:13 +0100 Subject: [PATCH 7/9] Cleanup mock --- .../cryomagnetics/_cryomagnetics4g.py | 17 ++++++++++------- tests/drivers/test_cryomagnetics_4g.py | 11 ++++++----- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/qcodes/instrument_drivers/cryomagnetics/_cryomagnetics4g.py b/src/qcodes/instrument_drivers/cryomagnetics/_cryomagnetics4g.py index ef31232682ef..0f652be3017a 100644 --- a/src/qcodes/instrument_drivers/cryomagnetics/_cryomagnetics4g.py +++ b/src/qcodes/instrument_drivers/cryomagnetics/_cryomagnetics4g.py @@ -3,7 +3,8 @@ import re import time from dataclasses import dataclass -from typing import TYPE_CHECKING +from time import time as _time +from typing import TYPE_CHECKING, Self from pyvisa import VisaIOError @@ -84,6 +85,8 @@ def __init__( # Initialize rate manager based on hypothetical hardware specific limits self._initialize_max_current_limits() + self._stability_check_interval = 20 + # Adding parameters self.units: Parameter = self.add_parameter( name="units", @@ -95,7 +98,7 @@ def __init__( ) """Field Units""" - self.ramping_state_check_interval: Parameter = self.add_parameter( + self.ramping_state_check_interval: Parameter[float, Self] = self.add_parameter( "ramping_state_check_interval", initial_value=0.05, unit="s", @@ -319,8 +322,7 @@ def wait_while_ramping( if getattr(self, "visabackend", False) == "sim": # write setpoint directly in sim mode self.write(f"IMAG {value / self.KG_TO_TESLA}") - last_check_time = time.time() - stability_check_interval = 20 + last_check_time = _time() last_stable_field = self._get_field() while True: @@ -329,8 +331,9 @@ def wait_while_ramping( if setpoint_reached: break - elapsed_time = time.time() - last_check_time - time_for_stability_check = elapsed_time > stability_check_interval + current_time = _time() + elapsed_time = current_time - last_check_time + time_for_stability_check = elapsed_time > self._stability_check_interval field_is_stable = abs(last_stable_field - current_field) < threshold if time_for_stability_check and field_is_stable: @@ -340,7 +343,7 @@ def wait_while_ramping( ) elif time_for_stability_check and not field_is_stable: last_stable_field = current_field - last_check_time = time.time() + last_check_time = current_time self._sleep(self.ramping_state_check_interval()) self.write("SWEEP PAUSE") diff --git a/tests/drivers/test_cryomagnetics_4g.py b/tests/drivers/test_cryomagnetics_4g.py index 7f513d73085d..3459f7a89442 100644 --- a/tests/drivers/test_cryomagnetics_4g.py +++ b/tests/drivers/test_cryomagnetics_4g.py @@ -121,24 +121,25 @@ def test_set_field_blocking(cryo_instrument): mock_wait.assert_called_once_with(0.5, threshold=ANY) -def test_wait_while_ramping_timeout(cryo_instrument): +def test_wait_while_ramping_timeout(cryo_instrument: CryomagneticsModel4G) -> None: # Simulate _get_field always returning a value far from the setpoint. # Mock time.time() to simulate 21s passing, avoiding real 20s wait # for stability_check_interval timeout. call_count = 0 - def mock_time(): + def mock_time() -> float: nonlocal call_count call_count += 1 # First call sets last_check_time, subsequent calls exceed the - # 20s stability_check_interval - return 0.0 if call_count <= 1 else 21.0 + # stability_check_interval + sleep_time = cryo_instrument.ramping_state_check_interval() + return call_count * sleep_time with ( patch.object(cryo_instrument, "_get_field", return_value=0.0), patch.object(cryo_instrument, "_sleep"), patch( - "qcodes.instrument_drivers.cryomagnetics._cryomagnetics4g.time.time", + "qcodes.instrument_drivers.cryomagnetics._cryomagnetics4g._time", side_effect=mock_time, ), ): From aa5a94612e784931999a2b632d225eb8d01731b8 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 26 Mar 2026 09:38:37 +0100 Subject: [PATCH 8/9] Ensure test sleeps a resonable amount of times --- tests/drivers/test_cryomagnetics_4g.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/drivers/test_cryomagnetics_4g.py b/tests/drivers/test_cryomagnetics_4g.py index 3459f7a89442..ab0d10b020eb 100644 --- a/tests/drivers/test_cryomagnetics_4g.py +++ b/tests/drivers/test_cryomagnetics_4g.py @@ -123,17 +123,18 @@ def test_set_field_blocking(cryo_instrument): def test_wait_while_ramping_timeout(cryo_instrument: CryomagneticsModel4G) -> None: # Simulate _get_field always returning a value far from the setpoint. - # Mock time.time() to simulate 21s passing, avoiding real 20s wait - # for stability_check_interval timeout. + # Mock time.time() to simulate time passing without waiting call_count = 0 + interval_fraction = 5 def mock_time() -> float: nonlocal call_count - call_count += 1 # First call sets last_check_time, subsequent calls exceed the # stability_check_interval - sleep_time = cryo_instrument.ramping_state_check_interval() - return call_count * sleep_time + sleep_time = cryo_instrument._stability_check_interval / interval_fraction + new_time = call_count * sleep_time + call_count += 1 + return new_time with ( patch.object(cryo_instrument, "_get_field", return_value=0.0), From d67fa0d93fdc97517557d3df9dae842e7d4fd590 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 26 Mar 2026 09:46:20 +0100 Subject: [PATCH 9/9] Add types to tests --- tests/drivers/test_cryomagnetics_4g.py | 41 +++++++++++++++----------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/tests/drivers/test_cryomagnetics_4g.py b/tests/drivers/test_cryomagnetics_4g.py index ab0d10b020eb..0dbf37bb725f 100644 --- a/tests/drivers/test_cryomagnetics_4g.py +++ b/tests/drivers/test_cryomagnetics_4g.py @@ -1,4 +1,5 @@ import logging +from typing import TYPE_CHECKING from unittest.mock import ANY, MagicMock, call, patch import pytest @@ -9,9 +10,12 @@ CryomagneticsOperatingState, ) +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(name="cryo_instrument", scope="function") -def fixture_cryo_instrument(): +def fixture_cryo_instrument() -> "Generator[CryomagneticsModel4G,None,None]": """ Fixture to create and yield a CryomagneticsModel4G object and close it after testing. """ @@ -26,19 +30,19 @@ def fixture_cryo_instrument(): instrument.close() -def test_initialization(cryo_instrument): +def test_initialization(cryo_instrument: CryomagneticsModel4G) -> None: assert cryo_instrument.name == "test_cryo_4g" assert cryo_instrument._address == "GPIB::1::INSTR" # assert cryo_instrument.terminator == "\n" -def test_get_field(cryo_instrument): +def test_get_field(cryo_instrument: CryomagneticsModel4G) -> None: cryo_instrument.units = MagicMock(return_value="T") cryo_instrument.field(5.0) assert cryo_instrument.field() == 5.0 -def test_initialization_visa_sim(cryo_instrument): +def test_initialization_visa_sim(cryo_instrument: CryomagneticsModel4G) -> None: # Test to ensure correct initialization of the CryomagneticsModel4G instrument assert cryo_instrument.name == "test_cryo_4g" assert cryo_instrument._address == "GPIB::1::INSTR" @@ -65,24 +69,27 @@ def test_initialization_visa_sim(cryo_instrument): ], ) def test_magnet_operating_state( - cryo_instrument, - caplog, - status_byte, - expected_state, - expected_exception, - expected_log_message, -): + cryo_instrument: CryomagneticsModel4G, + caplog: pytest.LogCaptureFixture, + status_byte: str, + expected_state: CryomagneticsOperatingState | None, + expected_exception: type[Exception] | None, + expected_log_message: str | None, +) -> None: with patch.object(cryo_instrument, "ask", return_value=status_byte): if expected_exception: with pytest.raises(expected_exception, match=expected_log_message): cryo_instrument.magnet_operating_state() + assert expected_log_message is not None assert expected_log_message in caplog.text else: state = cryo_instrument.magnet_operating_state() assert state == expected_state -def test_set_field_successful(cryo_instrument, caplog): +def test_set_field_successful( + cryo_instrument: CryomagneticsModel4G, caplog: pytest.LogCaptureFixture +) -> None: with ( patch.object(cryo_instrument, "write") as mock_write, ): @@ -97,7 +104,7 @@ def test_set_field_successful(cryo_instrument, caplog): assert "Magnetic field is ramping but not currently blocked!" in caplog.text -def test_set_field_blocking(cryo_instrument): +def test_set_field_blocking(cryo_instrument: CryomagneticsModel4G) -> None: with ( patch.object(cryo_instrument, "write") as mock_write, patch.object( @@ -148,7 +155,7 @@ def mock_time() -> float: cryo_instrument.wait_while_ramping(1.0, threshold=1e-4) -def test_wait_while_ramping_success(cryo_instrument): +def test_wait_while_ramping_success(cryo_instrument: CryomagneticsModel4G) -> None: # Simulate _get_field returning values that reach the setpoint with ( patch.object(cryo_instrument, "_sleep"), @@ -163,12 +170,12 @@ def test_wait_while_ramping_success(cryo_instrument): assert state.ramping is False -def test_get_rate(cryo_instrument): +def test_get_rate(cryo_instrument: CryomagneticsModel4G) -> None: with patch.object(cryo_instrument, "ask", return_value="5.0"): assert cryo_instrument._get_rate() == 5.0 * 60 * cryo_instrument.coil_constant -def test_set_rate(cryo_instrument): +def test_set_rate(cryo_instrument: CryomagneticsModel4G) -> None: # Define the max_current_limits dictionary for testing cryo_instrument.max_current_limits = { 0: (10.0, 1.0), # Range 0: up to 10 A, max rate 1 A/s @@ -201,7 +208,7 @@ def test_set_rate(cryo_instrument): ] -def test_initialize_max_current_limits(cryo_instrument): +def test_initialize_max_current_limits(cryo_instrument: CryomagneticsModel4G) -> None: with patch.object(cryo_instrument, "write") as mock_write: cryo_instrument._initialize_max_current_limits() calls = [