Coverage for tests/test_tts_utils.py: 99%

79 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-09 04:47 +0000

1""" 

2Unit tests for tts_utils.py 

3""" 

4import os 

5import pytest 

6 

7from media_utils import empty_audio_file 

8from file_utils import read_file_base64 

9from media_utils import get_audio_duration 

10 

11from tts_utils import get_audio_chunks_by_silences 

12from tts_utils import split_into_sentences_max_duration 

13from tts_utils import strip_audio_file_silence 

14from tts_utils import generate_waveform_plt 

15from tts_utils import merge_chunks 

16 

17 

18def test_empy_audio_chunk() -> None: 

19 audio_path = empty_audio_file(duration_seconds=7.3) 

20 chunks = get_audio_chunks_by_silences(audio_path) 

21 assert len(chunks) == 2 

22 

23 chunk0 = chunks[0] 

24 assert chunk0[0] == 0.0 

25 assert chunk0[1] == 3.65 

26 

27 chunk1 = chunks[1] 

28 assert chunk1[0] == 3.65 

29 assert chunk1[1] == 7.3 

30 

31 

32def test_audio_sample_chunk() -> None: 

33 audio_path = "tests/data/audio_24secs.wav" 

34 if not os.path.exists(audio_path): 

35 return 

36 

37 chunks = get_audio_chunks_by_silences(audio_path) 

38 assert len(chunks) == 5 

39 assert chunks[0][0] == 0.0 

40 for chunk_start, chunk_end in chunks: 

41 assert chunk_start < chunk_end 

42 

43 

44def test_split_sentences() -> None: 

45 text = ("This is a test. " * 20) + ("This sentence is way too long " * 50) + ("Short one. " * 10) 

46 chunks = split_into_sentences_max_duration(text, max_duration=3.0) 

47 assert len(chunks) > 1 

48 for chunk in chunks: 

49 assert 0 < len(chunk) < 5000 # Arbitrary limit to avoid extremely long chunks 

50 

51 assert split_into_sentences_max_duration(None, max_duration=3.0) == [] # type: ignore[arg-type] 

52 assert split_into_sentences_max_duration("", max_duration=3.0) == [] 

53 assert split_into_sentences_max_duration(" ", max_duration=3.0) == [" "] 

54 assert split_into_sentences_max_duration(" Test ", max_duration=3.0) == [" Test "] 

55 assert split_into_sentences_max_duration(" Test1. Test2. ", max_duration=3.0) == [" Test1. Test2. "] 

56 

57 

58@pytest.mark.asyncio 

59async def test_fit_audio_to_duration() -> None: 

60 audio_path = "tests/data/audio_24secs.wav" 

61 audio_base64 = await read_file_base64(audio_path) 

62 duration_secs = get_audio_duration(audio_base64) 

63 assert duration_secs == 24.025 

64 

65 stripped_end_audio_path = strip_audio_file_silence(audio_path, strip_start=False, strip_end=True) 

66 stripped_end_audio_base64 = await read_file_base64(stripped_end_audio_path) 

67 assert stripped_end_audio_base64.startswith("UklGR") 

68 stripped_end_duration_secs = get_audio_duration(stripped_end_audio_base64) 

69 assert stripped_end_duration_secs < duration_secs 

70 os.unlink(stripped_end_audio_path) 

71 

72 stripped_audio_path = strip_audio_file_silence(audio_path, strip_start=True, strip_end=True) 

73 stripped_audio_base64 = await read_file_base64(stripped_audio_path) 

74 assert stripped_audio_base64.startswith("UklGR") 

75 stripped_duration_secs = get_audio_duration(stripped_audio_base64) 

76 assert stripped_duration_secs < stripped_end_duration_secs 

77 os.unlink(stripped_audio_path) 

78 

79 

80def test_generate_waveform_plt() -> None: 

81 audio_path = "tests/data/sample.wav" 

82 waveform_path = generate_waveform_plt(audio_path) 

83 assert waveform_path.endswith(".png") 

84 assert os.path.exists(waveform_path) 

85 assert os.path.getsize(waveform_path) > 0 

86 with open(waveform_path, "rb") as file: 

87 png_bytes = file.read() 

88 assert png_bytes.startswith(b"\x89PNG\r\n\x1a\n") 

89 os.unlink(waveform_path) 

90 

91 

92def test_merge_chunks() -> None: 

93 chunks = [(0.0, 1.5), (1.5, 2.0), (2.0, 3.0), (3.0, 5.0)] 

94 assert merge_chunks(chunks, max_duration_seconds=10.0) == [(0.0, 5.0)] 

95 assert merge_chunks(chunks, max_duration_seconds=5.0) == [(0.0, 5.0)] 

96 assert merge_chunks(chunks, max_duration_seconds=2.0) == [(0.0, 2.0), (2.0, 3.0), (3.0, 5.0)] 

97 assert merge_chunks(chunks, max_duration_seconds=1.0) == [(0.0, 1.5), (1.5, 2.0), (2.0, 3.0), (3.0, 5.0)] 

98 assert merge_chunks(chunks, max_duration_seconds=0.0) == [(0.0, 1.5), (1.5, 2.0), (2.0, 3.0), (3.0, 5.0)] 

99 assert merge_chunks(chunks, max_duration_seconds=-1.0) == [(0.0, 1.5), (1.5, 2.0), (2.0, 3.0), (3.0, 5.0)] 

100 

101 assert merge_chunks(None) is None # type: ignore[arg-type] 

102 assert merge_chunks([]) == [] 

103 assert merge_chunks([(0.0, 1.5)]) == [(0.0, 1.5)]