Skip to content

Commit

Permalink
Unit Test cases clean up, bug fixes, new functionality (#231)
Browse files Browse the repository at this point in the history
Unit Test cases clean up, bug fixes, new functionality
  • Loading branch information
vivekuppal authored Jun 10, 2024
1 parent a06b563 commit bdcf85c
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 57 deletions.
4 changes: 2 additions & 2 deletions app/transcribe/audio_transcriber.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ def transcribe_audio_queue(self, audio_queue: queue.Queue):
while True:
who_spoke, data, time_spoken = audio_queue.get()
logger.info(f'Transcribe Audio Queue. Current time: {datetime.datetime.utcnow()} '
f'- Time Spoken: {time_spoken} by : {who_spoke}, queue_backlog - '
f'{audio_queue.qsize()}')
f'- Time Spoken: {time_spoken} by : {who_spoke}, queue_backlog - '
f'{audio_queue.qsize()}')
self._update_last_sample_and_phrase_status(who_spoke, data, time_spoken)
source_info = self.audio_sources_properties[who_spoke]

Expand Down
59 changes: 59 additions & 0 deletions app/transcribe/tests/test_selectable_text.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import unittest
from tkinter import Tk
# from customtkinter import CTk

# Assuming SelectableTextComponent is defined in a module named selectable_text_component
from app.transcribe.uicomp.selectable_text import SelectableText


class TestSelectableText(unittest.TestCase):
def setUp(self):
# Set up a root window and the component for testing
self.root = Tk()
self.root.withdraw() # Hide the root window
self.component = SelectableText(self.root)
self.component.pack()

def tearDown(self):
self.component.destroy()
self.root.destroy()

def test_insert_text_at_top(self):
self.component.add_text_to_top("First line at top")
result = self.component.text_widget.get("1.0", "2.0").strip()
self.assertEqual(result, "First line at top")

def test_insert_text_at_bottom(self):
self.component.add_text_to_bottom("First line at bottom")
result = self.component.text_widget.get("end-2l", "end-1l").strip()
self.assertEqual(result, "First line at bottom")

def test_scroll_to_top(self):
self.component.add_text_to_top("Line 1\nLine 2\nLine 3\n")
self.component.scroll_to_bottom()
self.component.scroll_to_top()
self.assertEqual(self.component.text_widget.yview()[0], 0.0)

def test_scroll_to_bottom(self):
self.component.add_text_to_bottom("Line 1\nLine 2\nLine 3\n")
self.component.scroll_to_bottom()
self.assertEqual(self.component.text_widget.yview()[1], 1.0)

def test_delete_last_two_rows(self):
self.component.add_text_to_bottom("Line 1")
self.component.add_text_to_bottom("Line 2")
self.component.add_text_to_bottom("Line 3")
self.component.delete_last_2_row()
result = self.component.text_widget.get("1.0", "end").strip()
self.assertEqual(result, "Line 1")

def test_clear_all_text(self):
self.component.add_text_to_bottom("Line 1")
self.component.add_text_to_bottom("Line 2")
self.component.clear_all_text()
result = self.component.text_widget.get("1.0", "end").strip()
self.assertEqual(result, "")


if __name__ == '__main__':
unittest.main()
5 changes: 3 additions & 2 deletions custom_speech_recognition/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1513,7 +1513,8 @@ def recognize_ibm(self, audio_data, key, language="en-US", show_all=False):
transcription = []
confidence = None
for utterance in result["results"]:
if "alternatives" not in utterance: raise UnknownValueError()
if "alternatives" not in utterance:
raise UnknownValueError()
for hypothesis in utterance["alternatives"]:
if "transcript" in hypothesis:
transcription.append(hypothesis["transcript"])
Expand Down Expand Up @@ -1605,7 +1606,7 @@ def recognize_whisper(self, audio_data, model="base", show_dict=False, load_opti
task="translate" if translate else None,
# fp16=torch.cuda.is_available(),
fp16=False,
temperature=0,
# temperature=0,
**transcribe_options
)

Expand Down
5 changes: 4 additions & 1 deletion sdk/transcriber_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def __init__(self, stt_model_config: dict):
self.model_name = self.model + ".pt"
self.model_filename = os.path.join(MODELS_DIR, model_filename)
self.download_model()
self.audio_model = whisper.load_model(self.model_filename)
self.audio_model: whisper.Whisper = whisper.load_model(self.model_filename)
print(f'[INFO] Speech To Text - Whisper using GPU: {str(torch.cuda.is_available())}')
openai.api_key = stt_model_config["api_key"]

Expand Down Expand Up @@ -142,6 +142,9 @@ def get_transcription(self, wav_file_path) -> dict:
"""Get transcription from the provided audio file
"""
try:
# For translation provide a decode_option for task=translate
# options = {}
# options['task'] = 'translate'
result = self.audio_model.transcribe(wav_file_path,
fp16=False,
language=self.lang,
Expand Down
Binary file added tests/english.wav
Binary file not shown.
127 changes: 80 additions & 47 deletions tests/test_recognition.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@

class TestRecognition(unittest.TestCase):
def setUp(self):
self.AUDIO_FILE_EN = os.path.join(os.path.dirname(os.path.realpath(__file__)), "english.wav")
self.AUDIO_FILE_FR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "french.aiff")
self.AUDIO_FILE_ZH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "chinese.flac")
self.AUDIO_FILE_EN = os.path.join(os.path.dirname(os.path.realpath(__file__)),
"english.wav")
self.AUDIO_FILE_FR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
"french.aiff")
self.AUDIO_FILE_ZH = os.path.join(os.path.dirname(os.path.realpath(__file__)),
"chinese.flac")
self.WHISPER_CONFIG = {"temperature": 0}

# def test_sphinx_english(self):
Expand All @@ -21,82 +24,112 @@ def setUp(self):

def test_google_english(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_EN) as source: audio = r.record(source)
with sr.AudioFile(self.AUDIO_FILE_EN) as source:
audio = r.record(source)
result = r.recognize_google(audio)
self.assertIn(result, ["1 2"])
self.assertIn(result, ["1 2"], f'Expected ["1 2"] got {result}')

def test_google_french(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_FR) as source: audio = r.record(source)
self.assertEqual(r.recognize_google(audio, language="fr-FR"), u"et c'est la dictée numéro 1")
with sr.AudioFile(self.AUDIO_FILE_FR) as source:
audio = r.record(source)
self.assertEqual(r.recognize_google(audio, language="fr-FR"), "et c'est la dictée numéro 1")

def test_google_chinese(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_ZH) as source: audio = r.record(source)
self.assertEqual(r.recognize_google(audio, language="zh-CN"), u"砸自己的脚")
# def test_google_chinese(self):
# r = sr.Recognizer()
# with sr.AudioFile(self.AUDIO_FILE_ZH) as source: audio = r.record(source)
# self.assertEqual(r.recognize_google(audio, language="zh-CN"), "砸自己的脚")

@unittest.skipUnless("WIT_AI_KEY" in os.environ, "requires Wit.ai key to be specified in WIT_AI_KEY environment variable")
@unittest.skipUnless("WIT_AI_KEY" in os.environ, "requires Wit.ai key to be specified in WIT_AI_KEY "
+ "environment variable")
def test_wit_english(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_EN) as source: audio = r.record(source)
with sr.AudioFile(self.AUDIO_FILE_EN) as source:
audio = r.record(source)
self.assertEqual(r.recognize_wit(audio, key=os.environ["WIT_AI_KEY"]), "one two three")

@unittest.skipUnless("BING_KEY" in os.environ, "requires Microsoft Bing Voice Recognition key to be specified in BING_KEY environment variable")
@unittest.skipUnless("BING_KEY" in os.environ, "requires Microsoft Bing Voice Recognition key to be "
+ "specified in BING_KEY environment variable")
def test_bing_english(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_EN) as source: audio = r.record(source)
with sr.AudioFile(self.AUDIO_FILE_EN) as source:
audio = r.record(source)
self.assertEqual(r.recognize_bing(audio, key=os.environ["BING_KEY"]), "123.")

@unittest.skipUnless("BING_KEY" in os.environ, "requires Microsoft Bing Voice Recognition key to be specified in BING_KEY environment variable")
@unittest.skipUnless("BING_KEY" in os.environ, "requires Microsoft Bing Voice Recognition key to be "
+ "specified in BING_KEY environment variable")
def test_bing_french(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_FR) as source: audio = r.record(source)
self.assertEqual(r.recognize_bing(audio, key=os.environ["BING_KEY"], language="fr-FR"), u"Essaye la dictée numéro un.")
with sr.AudioFile(self.AUDIO_FILE_FR) as source:
audio = r.record(source)
self.assertEqual(r.recognize_bing(audio, key=os.environ["BING_KEY"], language="fr-FR"),
"Essaye la dictée numéro un.")

@unittest.skipUnless("BING_KEY" in os.environ, "requires Microsoft Bing Voice Recognition key to be specified in BING_KEY environment variable")
@unittest.skipUnless("BING_KEY" in os.environ, "requires Microsoft Bing Voice Recognition key to be "
+ "specified in BING_KEY environment variable")
def test_bing_chinese(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_ZH) as source: audio = r.record(source)
self.assertEqual(r.recognize_bing(audio, key=os.environ["BING_KEY"], language="zh-CN"), u"砸自己的脚。")
with sr.AudioFile(self.AUDIO_FILE_ZH) as source:
audio = r.record(source)
self.assertEqual(r.recognize_bing(audio, key=os.environ["BING_KEY"], language="zh-CN"), "砸自己的脚。")

@unittest.skipUnless("HOUNDIFY_CLIENT_ID" in os.environ and "HOUNDIFY_CLIENT_KEY" in os.environ, "requires Houndify client ID and client key to be specified in HOUNDIFY_CLIENT_ID and HOUNDIFY_CLIENT_KEY environment variables")
@unittest.skipUnless("HOUNDIFY_CLIENT_ID" in os.environ and "HOUNDIFY_CLIENT_KEY" in os.environ,
"requires Houndify client ID and client key to be specified in HOUNDIFY_CLIENT_ID "
+ "and HOUNDIFY_CLIENT_KEY environment variables")
def test_houndify_english(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_EN) as source: audio = r.record(source)
self.assertEqual(r.recognize_houndify(audio, client_id=os.environ["HOUNDIFY_CLIENT_ID"], client_key=os.environ["HOUNDIFY_CLIENT_KEY"]), "one two three")

@unittest.skipUnless("IBM_USERNAME" in os.environ and "IBM_PASSWORD" in os.environ, "requires IBM Speech to Text username and password to be specified in IBM_USERNAME and IBM_PASSWORD environment variables")
def test_ibm_english(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_EN) as source: audio = r.record(source)
self.assertEqual(r.recognize_ibm(audio, username=os.environ["IBM_USERNAME"], password=os.environ["IBM_PASSWORD"]), "one two three ")

@unittest.skipUnless("IBM_USERNAME" in os.environ and "IBM_PASSWORD" in os.environ, "requires IBM Speech to Text username and password to be specified in IBM_USERNAME and IBM_PASSWORD environment variables")
def test_ibm_french(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_FR) as source: audio = r.record(source)
self.assertEqual(r.recognize_ibm(audio, username=os.environ["IBM_USERNAME"], password=os.environ["IBM_PASSWORD"], language="fr-FR"), u"si la dictée numéro un ")

@unittest.skipUnless("IBM_USERNAME" in os.environ and "IBM_PASSWORD" in os.environ, "requires IBM Speech to Text username and password to be specified in IBM_USERNAME and IBM_PASSWORD environment variables")
def test_ibm_chinese(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_ZH) as source: audio = r.record(source)
self.assertEqual(r.recognize_ibm(audio, username=os.environ["IBM_USERNAME"], password=os.environ["IBM_PASSWORD"], language="zh-CN"), u"砸 自己 的 脚 ")
with sr.AudioFile(self.AUDIO_FILE_EN) as source:
audio = r.record(source)
self.assertEqual(r.recognize_houndify(audio, client_id=os.environ["HOUNDIFY_CLIENT_ID"],
client_key=os.environ["HOUNDIFY_CLIENT_KEY"]),
"one two three")

# All IBM related test cases are commented because the parameters are incorrect
# @unittest.skipUnless("IBM_USERNAME" in os.environ and "IBM_PASSWORD" in os.environ,
# "requires IBM Speech to Text username and password to be specified in IBM_USERNAME \
# and IBM_PASSWORD environment variables")
# def test_ibm_english(self):
# r = sr.Recognizer()
# with sr.AudioFile(self.AUDIO_FILE_EN) as source:
# audio = r.record(source)
# self.assertEqual(r.recognize_ibm(audio, username=os.environ["IBM_USERNAME"],
# password=os.environ["IBM_PASSWORD"]), "one two three ")

# @unittest.skipUnless("IBM_USERNAME" in os.environ and "IBM_PASSWORD" in os.environ, "requires IBM Speech"
# + " to Text username and password to be specified in IBM_USERNAME and IBM_PASSWORD"
# + " environment variables")
# def test_ibm_french(self):
# r = sr.Recognizer()
# with sr.AudioFile(self.AUDIO_FILE_FR) as source:
# audio = r.record(source)
# self.assertEqual(r.recognize_ibm(audio, username=os.environ["IBM_USERNAME"], password=os.environ["IBM_PASSWORD"], language="fr-FR"), "si la dictée numéro un ")

# @unittest.skipUnless("IBM_USERNAME" in os.environ and "IBM_PASSWORD" in os.environ, "requires IBM Speech to Text username and password to be specified in IBM_USERNAME and IBM_PASSWORD environment variables")
# def test_ibm_chinese(self):
# r = sr.Recognizer()
# with sr.AudioFile(self.AUDIO_FILE_ZH) as source:
# audio = r.record(source)
# self.assertEqual(r.recognize_ibm(audio, username=os.environ["IBM_USERNAME"], password=os.environ["IBM_PASSWORD"], language="zh-CN"), "砸 自己 的 脚 ")

def test_whisper_english(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_EN) as source: audio = r.record(source)
with sr.AudioFile(self.AUDIO_FILE_EN) as source:
audio = r.record(source)
self.assertEqual(r.recognize_whisper(audio, language="english", **self.WHISPER_CONFIG), " 1, 2, 3.")

def test_whisper_french(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_FR) as source: audio = r.record(source)
self.assertEqual(r.recognize_whisper(audio, language="french", **self.WHISPER_CONFIG), " et c'est la dictée numéro 1.")
with sr.AudioFile(self.AUDIO_FILE_FR) as source:
audio = r.record(source)
self.assertEqual(r.recognize_whisper(audio, language="french", **self.WHISPER_CONFIG),
" et c'est la dictée numéro 1.")

def test_whisper_chinese(self):
r = sr.Recognizer()
with sr.AudioFile(self.AUDIO_FILE_ZH) as source: audio = r.record(source)
self.assertEqual(r.recognize_whisper(audio, model="small", language="chinese", **self.WHISPER_CONFIG), u"砸自己的腳")
with sr.AudioFile(self.AUDIO_FILE_ZH) as source:
audio = r.record(source)
self.assertEqual(r.recognize_whisper(audio, model="small", language="chinese", **self.WHISPER_CONFIG), "砸自己的腳")


if __name__ == "__main__":
unittest.main()
4 changes: 2 additions & 2 deletions tsutils/app_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
import logging
from logging import handlers
import logging.config
import constants
from tsutils import utilities

root_logger: logging.Logger = logging.getLogger(name=constants.LOG_NAME)
root_logger: logging.Logger = logging.getLogger(name='Transcribe')
AUDIO_PLAYER_LOGGER: str = 'audio_player'
TRANSCRIBER_LOGGER: str = 'transcriber'
GPT_RESPONDER_LOGGER: str = 'gpt_responder'
Expand Down Expand Up @@ -93,6 +92,7 @@ def setup_logging(log_file_name: str):
'class': 'logging.FileHandler',
'filename': log_file_name,
'formatter': 'standard',
'encoding': 'utf-8'
},
},
'loggers': {
Expand Down
Empty file added tsutils/tests/__init__.py
Empty file.
21 changes: 21 additions & 0 deletions tsutils/tests/test_duration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import unittest
from unittest.mock import patch
import datetime
from tsutils.duration import Duration


class TestDuration(unittest.TestCase):
"""Unit Tests for Duration class
"""

@patch('datetime.datetime')
def test_enter_method(self, mock_datetime):
"""Test that __enter__ method records the start time correctly."""
mock_datetime.now.return_value = datetime.datetime(2023, 1, 1, 12, 0, 0)
duration = Duration()
with duration:
self.assertEqual(duration.start, datetime.datetime(2023, 1, 1, 12, 0, 0))


if __name__ == '__main__':
unittest.main()
50 changes: 50 additions & 0 deletions tsutils/tests/test_utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import unittest
from unittest.mock import patch
from tsutils.utilities import (
merge, incrementing_filename, naturalsize,
download_using_bits, ensure_directory_exists
)


class TestFunctions(unittest.TestCase):

def test_merge(self):
first = {'a': 1, 'b': {'c': 3}}
second = {'b': {'d': 4}, 'e': 5}
result = merge(first, second)
self.assertEqual(result, {'a': 1, 'b': {'c': 3, 'd': 4}, 'e': 5})

@patch('os.path.exists', side_effect=[True, True, False])
def test_incrementing_filename(self, mock_exists):
result = incrementing_filename('file', 'txt')
self.assertEqual(result, 'file-2.txt')

def test_naturalsize(self):
result = naturalsize(3000000)
self.assertEqual(result, '3.0 MB')
result = naturalsize(300, False, True)
self.assertEqual(result, '300.0B', f'Expected 300.0B got {result}')

@patch('subprocess.check_output')
def test_download_using_bits(self, mock_subproc):
download_using_bits('https://github.com/vivekuppal/transcribe/archive/refs/heads/main.zip', 'transcribe.zip')
mock_subproc.assert_called_once_with(['powershell',
'-NoProfile',
'-ExecutionPolicy',
'Bypass',
'-Command',
'Start-BitsTransfer',
'-Source',
'https://github.com/vivekuppal/transcribe/archive/refs/heads/main.zip',
'-Destination',
'transcribe.zip'])

@patch('os.makedirs')
@patch('os.path.exists', return_value=False)
def test_ensure_directory_exists(self, mock_exists, mock_makedirs):
ensure_directory_exists('.')
mock_makedirs.assert_called_once_with('.')


if __name__ == '__main__':
unittest.main()
6 changes: 3 additions & 3 deletions tsutils/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,9 @@ def ensure_directory_exists(directory_path: str):
"""
if not os.path.exists(directory_path):
os.makedirs(directory_path)
print(f"Directory '{directory_path}' created.")
else:
print(f"Directory '{directory_path}' already exists.")
# print(f"Directory '{directory_path}' created.")
# else:
# print(f"Directory '{directory_path}' already exists.")


def get_data_path(app_name, filename=''):
Expand Down

0 comments on commit bdcf85c

Please sign in to comment.