22Test configuration for speech_recognition package.
33Ensures proper Python environment setup for speech/AI dependencies.
44"""
5+
6+ import gc
57import os
68import sys
79from unittest .mock import MagicMock
810
11+ import pytest
12+
913# Mock silero_vad.data immediately to prevent import errors during collection
1014mock_silero_data = MagicMock ()
11- sys .modules [' silero_vad.data' ] = mock_silero_data
15+ sys .modules [" silero_vad.data" ] = mock_silero_data
1216
1317# Setup environment for speech_recognition (uses unified ros_python_env)
1418DIARIZATION_ENV_PATH = "/opt/ros_python_env"
2832# Mock heavy AI/ML dependencies for testing
2933def setup_ml_mocks ():
3034 """Setup mock dependencies for ML/AI testing without requiring full models"""
31- from unittest .mock import MagicMock , patch
32-
35+ from unittest .mock import MagicMock
36+
3337 # Mock torch and torchaudio
3438 try :
3539 import torch
3640 import torchaudio
41+
3742 print (f"[pytest] Using real PyTorch: { torch .__version__ } " )
3843 except ImportError :
3944 print ("[pytest] Mocking PyTorch dependencies" )
@@ -43,13 +48,13 @@ def setup_ml_mocks():
4348 mock_torch .hub .load = MagicMock ()
4449 mock_torch .tensor = MagicMock ()
4550 mock_torch .jit .load = MagicMock ()
46-
51+
4752 mock_torchaudio = MagicMock ()
4853 mock_torchaudio .functional .resample = MagicMock ()
49-
50- sys .modules [' torch' ] = mock_torch
51- sys .modules [' torchaudio' ] = mock_torchaudio
52-
54+
55+ sys .modules [" torch" ] = mock_torch
56+ sys .modules [" torchaudio" ] = mock_torchaudio
57+
5358 # Mock faster_whisper
5459 try :
5560 import faster_whisper
@@ -58,8 +63,8 @@ def setup_ml_mocks():
5863 mock_whisper = MagicMock ()
5964 mock_whisper .WhisperModel = MagicMock ()
6065 mock_whisper .BatchedInferencePipeline = MagicMock ()
61- sys .modules [' faster_whisper' ] = mock_whisper
62-
66+ sys .modules [" faster_whisper" ] = mock_whisper
67+
6368 # Mock diart
6469 try :
6570 import diart
@@ -69,37 +74,37 @@ def setup_ml_mocks():
6974 mock_diart .SpeakerDiarization = MagicMock ()
7075 mock_diart .SpeakerDiarizationConfig = MagicMock ()
7176 mock_diart .models = MagicMock ()
72- sys .modules [' diart' ] = mock_diart
73- sys .modules [' diart.models' ] = mock_diart .models
74-
77+ sys .modules [" diart" ] = mock_diart
78+ sys .modules [" diart.models" ] = mock_diart .models
79+
7580 # Mock pyannote
7681 try :
7782 import pyannote
7883 except ImportError :
7984 print ("[pytest] Mocking pyannote" )
8085 mock_pyannote = MagicMock ()
8186 mock_pyannote .core .Annotation = MagicMock ()
82- sys .modules [' pyannote' ] = mock_pyannote
83- sys .modules [' pyannote.core' ] = mock_pyannote .core
84-
87+ sys .modules [" pyannote" ] = mock_pyannote
88+ sys .modules [" pyannote.core" ] = mock_pyannote .core
89+
8590 # Mock openwakeword
8691 try :
8792 import openwakeword
8893 except ImportError :
8994 print ("[pytest] Mocking openwakeword" )
90- sys .modules [' openwakeword' ] = MagicMock ()
91-
95+ sys .modules [" openwakeword" ] = MagicMock ()
96+
9297 # Mock silero_vad module that's causing the import error
9398 mock_silero = MagicMock ()
9499 mock_silero .model .load_silero_vad = MagicMock ()
95100 mock_silero .utils_vad .init_jit_model = MagicMock ()
96101 mock_silero .utils_vad .OnnxWrapper = MagicMock ()
97102 mock_silero .data = MagicMock () # Mock the missing data submodule
98- sys .modules [' silero_vad' ] = mock_silero
99- sys .modules [' silero_vad.model' ] = mock_silero .model
100- sys .modules [' silero_vad.utils_vad' ] = mock_silero .utils_vad
101- sys .modules [' silero_vad.data' ] = mock_silero .data
102-
103+ sys .modules [" silero_vad" ] = mock_silero
104+ sys .modules [" silero_vad.model" ] = mock_silero .model
105+ sys .modules [" silero_vad.utils_vad" ] = mock_silero .utils_vad
106+ sys .modules [" silero_vad.data" ] = mock_silero .data
107+
103108 print ("[pytest] ML dependency mocking completed" )
104109
105110
@@ -110,12 +115,24 @@ def setup_ml_mocks():
110115# Basic pytest configuration
111116def pytest_configure (config ):
112117 """Configure pytest for speech recognition tests"""
113- config .addinivalue_line (
114- "markers" , "unit: Unit tests for speech components"
115- )
116- config .addinivalue_line (
117- "markers" , "integration: Integration tests with ROS"
118- )
119- config .addinivalue_line (
120- "markers" , "slow: Tests that require model loading"
121- )
118+ config .addinivalue_line ("markers" , "unit: Unit tests for speech components" )
119+ config .addinivalue_line ("markers" , "integration: Integration tests with ROS" )
120+ config .addinivalue_line ("markers" , "slow: Tests that require model loading" )
121+
122+
123+ # Memory optimization hooks
124+ @pytest .fixture (autouse = True )
125+ def cleanup_after_test ():
126+ """Force garbage collection after each test to prevent memory buildup"""
127+ yield
128+ gc .collect ()
129+
130+
131+ def pytest_runtest_teardown (item , nextitem ):
132+ """Force garbage collection between tests to free memory"""
133+ gc .collect ()
134+
135+
136+ def pytest_sessionfinish (session , exitstatus ):
137+ """Final cleanup after all tests complete"""
138+ gc .collect ()
0 commit comments