chore: applied all feedback

close: N25B-298
This commit is contained in:
Pim Hutting
2025-11-22 11:45:32 +01:00
parent 051f904576
commit c53307530b
12 changed files with 53 additions and 212 deletions

View File

@@ -23,9 +23,6 @@ class MicrophoneUtils(object):
The result must contain at least "index", as this is used to identify the microphone,
and "name" for logging. It must have one or more channels (`maxInputChannels`),
and a default sample rate of at least 16000 Hz.
:param pyaudio_instance: A mocked or real PyAudio instance used to query microphone information.
:type pyaudio_instance: PyAudio
"""
result = choose_mic_default(pyaudio_instance)
assert "index" in result
@@ -47,12 +44,6 @@ class MicrophoneUtils(object):
Tests the robustness of the interactive selection when the user first enters
a non-integer value, ensuring the system prompts again without error and accepts
a valid integer on the second attempt.
:param pyaudio_instance: A mocked or real PyAudio instance.
:type pyaudio_instance: PyAudio
:param mocker: The fixture used for mocking built-in functions and system objects.
:type mocker: pytest_mock.plugin.MockerFixture
"""
microphones = get_microphones(pyaudio_instance)
target_microphone = next(microphones)
@@ -74,12 +65,6 @@ class MicrophoneUtils(object):
"""
Tests that the interactive selection method prevents the user from entering
a negative integer as a microphone index.
:param pyaudio_instance: A mocked or real PyAudio instance.
:type pyaudio_instance: PyAudio
:param mocker: The fixture used for mocking built-in functions and system objects.
:type mocker: pytest_mock.plugin.MockerFixture
"""
microphones = get_microphones(pyaudio_instance)
target_microphone = next(microphones)
@@ -101,12 +86,6 @@ class MicrophoneUtils(object):
"""
Tests that the interactive selection method prevents the user from entering
an index that exceeds the total number of available microphones.
:param pyaudio_instance: A mocked or real PyAudio instance.
:type pyaudio_instance: PyAudio
:param mocker: The fixture used for mocking built-in functions and system objects.
:type mocker: pytest_mock.plugin.MockerFixture
"""
real_count = len(list(get_microphones(pyaudio_instance)))
mock_input = mocker.patch("__builtin__.raw_input", side_effect=[str(real_count), "0"])
@@ -126,12 +105,6 @@ class MicrophoneUtils(object):
Tests the core interactive functionality by simulating the selection of a
random valid microphone index and verifying that the correct microphone
information is returned.
:param pyaudio_instance: A mocked or real PyAudio instance.
:type pyaudio_instance: PyAudio
:param mocker: The fixture used for mocking built-in functions and system objects.
:type mocker: pytest_mock.plugin.MockerFixture
"""
microphones = list(get_microphones(pyaudio_instance))
random_index = random.randrange(len(microphones))
@@ -143,6 +116,9 @@ class MicrophoneUtils(object):
assert result["index"] == microphones[random_index]["index"]
def test_choose_mic_no_arguments(self, pyaudio_instance, mocker):
"""
Tests `choose_mic_arguments` when no command-line arguments are provided,
"""
mocker.patch.object(sys, "argv", [])
result = choose_mic_arguments(pyaudio_instance)
@@ -153,12 +129,6 @@ class MicrophoneUtils(object):
"""
Tests `choose_mic_arguments` when the microphone name is passed as a separate
argument.
:param pyaudio_instance: A mocked or real PyAudio instance.
:type pyaudio_instance: PyAudio
:param mocker: The fixture used for mocking built-in functions and system objects.
:type mocker: pytest_mock.plugin.MockerFixture
"""
for mic in get_microphones(pyaudio_instance):
mocker.patch.object(sys, "argv", ["--microphone", mic["name"]])
@@ -172,12 +142,6 @@ class MicrophoneUtils(object):
"""
Tests `choose_mic_arguments` when the microphone name is passed using an
equals sign (`--microphone=NAME`).
:param pyaudio_instance: A mocked or real PyAudio instance.
:type pyaudio_instance: PyAudio
:param mocker: The fixture used for mocking built-in functions and system objects.
:type mocker: pytest_mock.plugin.MockerFixture
"""
for mic in get_microphones(pyaudio_instance):
mocker.patch.object(sys, "argv", ["--microphone={}".format(mic["name"])])
@@ -191,12 +155,6 @@ class MicrophoneUtils(object):
"""
Tests `choose_mic_arguments` when a non-existent microphone name is passed
via command-line arguments, expecting the function to return None.
:param pyaudio_instance: A mocked or real PyAudio instance.
:type pyaudio_instance: PyAudio
:param mocker: The fixture used for mocking built-in functions and system objects.
:type mocker: pytest_mock.plugin.MockerFixture
"""
mocker.patch.object(sys, "argv", ["--microphone", "Surely this microphone doesn't exist"])
@@ -208,12 +166,6 @@ class MicrophoneUtils(object):
"""
Tests `choose_mic` function when a valid microphone is
specified via command-line arguments.
:param pyaudio_instance: A mocked or real PyAudio instance.
:type pyaudio_instance: PyAudio
:param mocker: The fixture used for mocking built-in functions and system objects.
:type mocker: pytest_mock.plugin.MockerFixture
"""
mic = next(get_microphones(pyaudio_instance))
mocker.patch.object(sys, "argv", ["--microphone", mic["name"]])
@@ -228,12 +180,6 @@ class MicrophoneUtils(object):
Tests `choose_mic` function when no command-line arguments
are provided, verifying that the function falls back correctly to the
system's default microphone selection.
:param pyaudio_instance: A mocked or real PyAudio instance.
:type pyaudio_instance: PyAudio
:param mocker: The fixture used for mocking built-in functions and system objects.
:type mocker: pytest_mock.plugin.MockerFixture
"""
default_mic = choose_mic_default(pyaudio_instance)
mocker.patch.object(sys, "argv", [])

View File

@@ -23,9 +23,6 @@ def test_handle_unimplemented_endpoint(zmq_context):
"""
Tests that the ``ActuationReceiver.handle_message`` method can
handle an unknown or unimplemented endpoint without raising an error.
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
"""
receiver = ActuationReceiver(zmq_context)
# Should not error
@@ -39,12 +36,6 @@ def test_speech_message_no_data(zmq_context, mocker):
"""
Tests that the message handler logs a warning when a speech actuation
request (`actuate/speech`) is received but contains empty string data.
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
:param mocker: The pytest-mock fixture used to patch `logging.warn`.
:type mocker: pytest_mock.plugin.MockerFixture
"""
mock_warn = mocker.patch("logging.warn")
@@ -58,12 +49,6 @@ def test_speech_message_invalid_data(zmq_context, mocker):
"""
Tests that the message handler logs a warning when a speech actuation
request (`actuate/speech`) is received with data that is not a string (e.g., a boolean).
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
:param mocker: The pytest-mock fixture used to patch `logging.warn`.
:type mocker: pytest_mock.plugin.MockerFixture
"""
mock_warn = mocker.patch("logging.warn")
@@ -77,12 +62,6 @@ def test_speech_no_qi(zmq_context, mocker):
"""
Tests the actuation receiver's behavior when processing a speech request
but the global state does not have an active QI session.
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
:param mocker: The pytest-mock fixture used to patch the global state.
:type mocker: pytest_mock.plugin.MockerFixture
"""
mock_state = mocker.patch("robot_interface.endpoints.actuation_receiver.state")
@@ -99,12 +78,6 @@ def test_speech(zmq_context, mocker):
"""
Tests the core speech actuation functionality by mocking the QI TextToSpeech
service and verifying that it is called correctly.
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
:param mocker: The pytest-mock fixture used to patch state and modules.
:type mocker: pytest_mock.plugin.MockerFixture
"""
mock_state = mocker.patch("robot_interface.endpoints.actuation_receiver.state")

View File

@@ -24,12 +24,6 @@ def zmq_context():
def test_no_microphone(zmq_context, mocker):
"""
Tests the scenario where no valid microphone can be chosen for recording.
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
:param mocker: The pytest-mock fixture used to patch internal dependencies.
:type mocker: pytest_mock.plugin.MockerFixture
"""
mock_info_logger = mocker.patch("robot_interface.endpoints.audio_sender.logger.info")
mock_choose_mic = mocker.patch("robot_interface.endpoints.audio_sender.choose_mic")
@@ -49,12 +43,6 @@ def test_unicode_mic_name(zmq_context, mocker):
"""
Tests the robustness of the `AudioSender` when handling microphone names
that contain Unicode characters.
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
:param mocker: The pytest-mock fixture used to patch internal dependencies.
:type mocker: pytest_mock.plugin.MockerFixture
"""
mocker.patch("robot_interface.endpoints.audio_sender.threading")
mock_choose_mic = mocker.patch("robot_interface.endpoints.audio_sender.choose_mic")
@@ -74,12 +62,6 @@ def test_unicode_mic_name(zmq_context, mocker):
def _fake_read(num_frames):
"""
Helper function to simulate reading raw audio data from a microphone stream.
:param num_frames: The number of audio frames requested.
:type num_frames: int
:return: A byte string containing random data, simulating audio.
:rtype: str
"""
return os.urandom(num_frames * 4)
@@ -87,9 +69,6 @@ def _fake_read(num_frames):
def test_sending_audio(mocker):
"""
Tests the successful sending of audio data over a ZeroMQ socket.
:param mocker: The pytest-mock fixture used to patch internal dependencies.
:type mocker: pytest_mock.plugin.MockerFixture
"""
mock_choose_mic = mocker.patch("robot_interface.endpoints.audio_sender.choose_mic")
mock_choose_mic.return_value = {"name": u"Some mic", "index": 0L}
@@ -118,9 +97,6 @@ def test_sending_audio(mocker):
def _fake_read_error(num_frames):
"""
Helper function to simulate an I/O error during microphone stream reading.
:param num_frames: The number of audio frames requested.
:type num_frames: int
"""
raise IOError()
@@ -128,9 +104,6 @@ def _fake_read_error(num_frames):
def test_break_microphone(mocker):
"""
Tests the error handling when the microphone stream breaks (raises an IOError).
:param mocker: The pytest-mock fixture used to patch internal dependencies.
:type mocker: pytest_mock.plugin.MockerFixture
"""
mock_choose_mic = mocker.patch("robot_interface.endpoints.audio_sender.choose_mic")
mock_choose_mic.return_value = {"name": u"Some mic", "index": 0L}

View File

@@ -20,9 +20,6 @@ def zmq_context():
def test_handle_ping(zmq_context):
"""
Tests the receiver's ability to handle the "ping" endpoint with data.
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
"""
receiver = MainReceiver(zmq_context)
response = receiver.handle_message({"endpoint": "ping", "data": "pong"})
@@ -37,9 +34,6 @@ def test_handle_ping_none(zmq_context):
"""
Tests the receiver's ability to handle the ping endpoint when the
data field is explicitly set to None.
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
"""
receiver = MainReceiver(zmq_context)
response = receiver.handle_message({"endpoint": "ping", "data": None})
@@ -54,12 +48,6 @@ def test_handle_ping_none(zmq_context):
def test_handle_negotiate_ports(mock_state, zmq_context):
"""
Tests the handling of the "negotiate/ports" endpoint.
:param mock_state: Mocked global application state.
:type mock_state: mock.Mock
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
"""
receiver = MainReceiver(zmq_context)
mock_state.sockets = [receiver]
@@ -85,9 +73,6 @@ def test_handle_unimplemented_endpoint(zmq_context):
"""
Tests that the receiver correctly handles a request to a completely
unknown or non-existent endpoint.
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
"""
receiver = MainReceiver(zmq_context)
response = receiver.handle_message({
@@ -108,9 +93,6 @@ def test_handle_unimplemented_negotiation_endpoint(zmq_context):
The expected behavior is to return a specific "negotiate/error" response
with a descriptive error string.
:param zmq_context: The ZeroMQ context fixture.
:type zmq_context: zmq.Context
"""
receiver = MainReceiver(zmq_context)
response = receiver.handle_message({

View File

@@ -15,7 +15,7 @@ class MockPyAudio:
the core PyAudio methods required for device enumeration.
:ivar devices: A list of dictionaries representing mock audio devices.
:type devices: List[Dict[str, Any]]
:vartype devices: List[Dict[str, Any]]
"""
def __init__(self):
# You can predefine fake device info here