diff --git a/api/pytest.ini b/api/pytest.ini index a8e3bbb1933..61288b3f3c1 100644 --- a/api/pytest.ini +++ b/api/pytest.ini @@ -5,3 +5,9 @@ markers = ot3_only: Test only functions using the OT3 hardware addopts = --color=yes --strict-markers asyncio_mode = auto + +# TODO this should be looked into being removed upon updating the Decoy library. The purpose of this warning is to +# catch missing attributes, but it raises for any property referenced in a test which accounts for about ~250 warnings +# which aren't serving any useful purpose and obscure other warnings. +filterwarnings = + ignore::decoy.warnings.MissingSpecAttributeWarning diff --git a/api/tests/opentrons/protocol_api/test_instrument_context.py b/api/tests/opentrons/protocol_api/test_instrument_context.py index 1b8445ed7b2..8282f660a44 100644 --- a/api/tests/opentrons/protocol_api/test_instrument_context.py +++ b/api/tests/opentrons/protocol_api/test_instrument_context.py @@ -1501,6 +1501,7 @@ def test_mix_no_lpd( mock_well = decoy.mock(cls=Well) bottom_location = Location(point=Point(1, 2, 3), labware=mock_well) + top_location = Location(point=Point(3, 2, 1), labware=None) input_location = Location(point=Point(2, 2, 2), labware=None) last_location = Location(point=Point(9, 9, 9), labware=None) @@ -1516,6 +1517,7 @@ def test_mix_no_lpd( mock_validation.validate_location(location=None, last_location=last_location) ).then_return(WellTarget(well=mock_well, location=None, in_place=False)) decoy.when(mock_well.bottom(z=1.0)).then_return(bottom_location) + decoy.when(mock_well.top()).then_return(top_location) decoy.when(mock_instrument_core.get_aspirate_flow_rate(1.23)).then_return(5.67) decoy.when(mock_instrument_core.get_dispense_flow_rate(1.23)).then_return(5.67) decoy.when(mock_instrument_core.has_tip()).then_return(True) @@ -1523,19 +1525,63 @@ def test_mix_no_lpd( subject.mix(repetitions=10, volume=10.0, location=input_location, rate=1.23) decoy.verify( - mock_instrument_core.aspirate(), # type: ignore[call-arg] - ignore_extra_args=True, - times=10, - ) - decoy.verify( - mock_instrument_core.dispense(), # type: ignore[call-arg] - ignore_extra_args=True, + mock_instrument_core.aspirate( + bottom_location, + mock_well._core, + 10.0, + 1.23, + 5.67, + False, + None, + ), times=10, ) + # Slight differences in dispense push-out logic for 2.14 and 2.15 api levels + if subject.api_version < APIVersion(2, 16): + decoy.verify( + mock_instrument_core.dispense( + bottom_location, + mock_well._core, + 10.0, + 1.23, + 5.67, + False, + None, + None, + ), + times=10, + ) + else: + decoy.verify( + mock_instrument_core.dispense( + bottom_location, + mock_well._core, + 10.0, + 1.23, + 5.67, + False, + 0.0, + None, + ), + times=9, + ) + decoy.verify( + mock_instrument_core.dispense( + bottom_location, + mock_well._core, + 10.0, + 1.23, + 5.67, + False, + None, + None, + ), + times=1, + ) + decoy.verify( - mock_instrument_core.liquid_probe_with_recovery(), # type: ignore[call-arg] - ignore_extra_args=True, + mock_instrument_core.liquid_probe_with_recovery(mock_well._core, top_location), times=0, ) @@ -1551,6 +1597,7 @@ def test_mix_with_lpd( """It should aspirate/dispense to a well several times and do 1 lpd.""" mock_well = decoy.mock(cls=Well) bottom_location = Location(point=Point(1, 2, 3), labware=mock_well) + top_location = Location(point=Point(3, 2, 1), labware=None) input_location = Location(point=Point(2, 2, 2), labware=None) last_location = Location(point=Point(9, 9, 9), labware=None) @@ -1566,6 +1613,7 @@ def test_mix_with_lpd( mock_validation.validate_location(location=None, last_location=last_location) ).then_return(WellTarget(well=mock_well, location=None, in_place=False)) decoy.when(mock_well.bottom(z=1.0)).then_return(bottom_location) + decoy.when(mock_well.top()).then_return(top_location) decoy.when(mock_instrument_core.get_aspirate_flow_rate(1.23)).then_return(5.67) decoy.when(mock_instrument_core.get_dispense_flow_rate(1.23)).then_return(5.67) decoy.when(mock_instrument_core.has_tip()).then_return(True) @@ -1577,19 +1625,45 @@ def test_mix_with_lpd( subject.liquid_presence_detection = True subject.mix(repetitions=10, volume=10.0, location=input_location, rate=1.23) decoy.verify( - mock_instrument_core.aspirate(), # type: ignore[call-arg] - ignore_extra_args=True, + mock_instrument_core.aspirate( + bottom_location, + mock_well._core, + 10.0, + 1.23, + 5.67, + False, + None, + ), times=10, ) decoy.verify( - mock_instrument_core.dispense(), # type: ignore[call-arg] - ignore_extra_args=True, - times=10, + mock_instrument_core.dispense( + bottom_location, + mock_well._core, + 10.0, + 1.23, + 5.67, + False, + 0.0, + None, + ), + times=9, + ) + decoy.verify( + mock_instrument_core.dispense( + bottom_location, + mock_well._core, + 10.0, + 1.23, + 5.67, + False, + None, + None, + ), + times=1, ) - decoy.verify( - mock_instrument_core.liquid_probe_with_recovery(), # type: ignore[call-arg] - ignore_extra_args=True, + mock_instrument_core.liquid_probe_with_recovery(mock_well._core, top_location), times=1, ) diff --git a/api/tests/opentrons/protocol_engine/commands/test_verify_tip_presence.py b/api/tests/opentrons/protocol_engine/commands/test_verify_tip_presence.py index 53eb1f5a59e..ef6d79629be 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_verify_tip_presence.py +++ b/api/tests/opentrons/protocol_engine/commands/test_verify_tip_presence.py @@ -23,13 +23,13 @@ async def test_verify_tip_presence_implementation( expectedState=TipPresenceStatus.PRESENT, ) - decoy.when( + result = await subject.execute(data) + + assert result == SuccessData(public=VerifyTipPresenceResult()) + decoy.verify( await tip_handler.verify_tip_presence( pipette_id="pipette-id", expected=TipPresenceStatus.PRESENT, + follow_singular_sensor=None, ) - ).then_return(None) - - result = await subject.execute(data) - - assert result == SuccessData(public=VerifyTipPresenceResult()) + ) diff --git a/api/tests/opentrons/protocol_engine/commands/unsafe/test_update_position_estimators.py b/api/tests/opentrons/protocol_engine/commands/unsafe/test_update_position_estimators.py index 79131994299..da381635ce3 100644 --- a/api/tests/opentrons/protocol_engine/commands/unsafe/test_update_position_estimators.py +++ b/api/tests/opentrons/protocol_engine/commands/unsafe/test_update_position_estimators.py @@ -37,11 +37,6 @@ async def test_update_position_estimators_implementation( decoy.when(gantry_mover.motor_axis_to_hardware_axis(MotorAxis.Y)).then_return( Axis.Y ) - decoy.when( - await ot3_hardware_api.update_axis_position_estimations( - [Axis.Z_L, Axis.P_L, Axis.X, Axis.Y] - ) - ).then_return(None) result = await subject.execute(data) diff --git a/api/tests/opentrons/protocol_engine/test_protocol_engine.py b/api/tests/opentrons/protocol_engine/test_protocol_engine.py index bc581114ab2..d7e4b32e02a 100644 --- a/api/tests/opentrons/protocol_engine/test_protocol_engine.py +++ b/api/tests/opentrons/protocol_engine/test_protocol_engine.py @@ -997,8 +997,7 @@ async def test_estop_noops_if_invalid( subject.estop() # Should not raise. decoy.verify( - action_dispatcher.dispatch(), # type: ignore - ignore_extra_args=True, + action_dispatcher.dispatch(expected_action), times=0, ) decoy.verify( diff --git a/api/tests/opentrons/protocol_runner/test_protocol_runner.py b/api/tests/opentrons/protocol_runner/test_protocol_runner.py index 2f06e27c2c2..15e0192175e 100644 --- a/api/tests/opentrons/protocol_runner/test_protocol_runner.py +++ b/api/tests/opentrons/protocol_runner/test_protocol_runner.py @@ -448,6 +448,7 @@ async def test_run_json_runner_stop_requested_stops_enqueuing( await run_func() +@pytest.mark.filterwarnings("ignore::decoy.warnings.RedundantVerifyWarning") @pytest.mark.parametrize( "schema_version, json_protocol", [