test_tts.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import pytest
  4. from unittest.mock import Mock
  5. from gtts.tts import gTTS, gTTSError
  6. from gtts.langs import _main_langs
  7. from gtts.lang import _extra_langs
  8. # Testing all languages takes some time.
  9. # Set TEST_LANGS envvar to choose languages to test.
  10. # * 'main': Languages extracted from the Web
  11. # * 'extra': Language set in Languages.EXTRA_LANGS
  12. # * 'all': All of the above
  13. # * <csv>: Languages tags list to test
  14. # Unset TEST_LANGS to test everything ('all')
  15. # See: langs_dict()
  16. """Construct a dict of suites of languages to test.
  17. { '<suite name>' : <list or dict of language tags> }
  18. ex.: { 'fetch' : {'en': 'English', 'fr': 'French'},
  19. 'extra' : {'en': 'English', 'fr': 'French'} }
  20. ex.: { 'environ' : ['en', 'fr'] }
  21. """
  22. env = os.environ.get("TEST_LANGS")
  23. if not env or env == "all":
  24. langs = _main_langs()
  25. langs.update(_extra_langs())
  26. elif env == "main":
  27. langs = _main_langs()
  28. elif env == "extra":
  29. langs = _extra_langs()
  30. else:
  31. env_langs = {l: l for l in env.split(",") if l}
  32. langs = env_langs
  33. @pytest.mark.net
  34. @pytest.mark.parametrize("lang", langs.keys(), ids=list(langs.values()))
  35. def test_TTS(tmp_path, lang):
  36. """Test all supported languages and file save"""
  37. text = "This is a test"
  38. """Create output .mp3 file successfully"""
  39. for slow in (False, True):
  40. filename = tmp_path / "test_{}_.mp3".format(lang)
  41. # Create gTTS and save
  42. tts = gTTS(text=text, lang=lang, slow=slow, lang_check=False)
  43. tts.save(filename)
  44. # Check if files created is > 1.5
  45. assert filename.stat().st_size > 1500
  46. @pytest.mark.net
  47. def test_unsupported_language_check():
  48. """Raise ValueError on unsupported language (with language check)"""
  49. lang = "xx"
  50. text = "Lorem ipsum"
  51. check = True
  52. with pytest.raises(ValueError):
  53. gTTS(text=text, lang=lang, lang_check=check)
  54. def test_empty_string():
  55. """Raise AssertionError on empty string"""
  56. text = ""
  57. with pytest.raises(AssertionError):
  58. gTTS(text=text)
  59. def test_no_text_parts(tmp_path):
  60. """Raises AssertionError on no content to send to API (no text_parts)"""
  61. text = " ..,\n"
  62. with pytest.raises(AssertionError):
  63. filename = tmp_path / "no_content.txt"
  64. tts = gTTS(text=text)
  65. tts.save(filename)
  66. # Test write_to_fp()/save() cases not covered elsewhere in this file
  67. @pytest.mark.net
  68. def test_bad_fp_type():
  69. """Raise TypeError if fp is not a file-like object (no .write())"""
  70. # Create gTTS and save
  71. tts = gTTS(text="test")
  72. with pytest.raises(TypeError):
  73. tts.write_to_fp(5)
  74. @pytest.mark.net
  75. def test_save(tmp_path):
  76. """Save .mp3 file successfully"""
  77. filename = tmp_path / "save.mp3"
  78. # Create gTTS and save
  79. tts = gTTS(text="test")
  80. tts.save(filename)
  81. # Check if file created is > 2k
  82. assert filename.stat().st_size > 2000
  83. @pytest.mark.net
  84. def test_get_bodies():
  85. """get request bodies list"""
  86. tts = gTTS(text="test", tld="com", lang="en")
  87. body = tts.get_bodies()[0]
  88. assert "test" in body
  89. # \"en\" url-encoded
  90. assert "%5C%22en%5C%22" in body
  91. def test_msg():
  92. """Test gTTsError internal exception handling
  93. Set exception message successfully"""
  94. error1 = gTTSError("test")
  95. assert "test" == error1.msg
  96. error2 = gTTSError()
  97. assert error2.msg is None
  98. def test_infer_msg():
  99. """Infer message successfully based on context"""
  100. # Without response:
  101. # Bad TLD
  102. ttsTLD = Mock(tld="invalid")
  103. errorTLD = gTTSError(tts=ttsTLD)
  104. assert (
  105. errorTLD.msg
  106. == "Failed to connect. Probable cause: Host 'https://translate.google.invalid/' is not reachable"
  107. )
  108. # With response:
  109. # 403
  110. tts403 = Mock()
  111. response403 = Mock(status_code=403, reason="aaa")
  112. error403 = gTTSError(tts=tts403, response=response403)
  113. assert (
  114. error403.msg
  115. == "403 (aaa) from TTS API. Probable cause: Bad token or upstream API changes"
  116. )
  117. # 200 (and not lang_check)
  118. tts200 = Mock(lang="xx", lang_check=False)
  119. response404 = Mock(status_code=200, reason="bbb")
  120. error200 = gTTSError(tts=tts200, response=response404)
  121. assert (
  122. error200.msg
  123. == "200 (bbb) from TTS API. Probable cause: No audio stream in response. Unsupported language 'xx'"
  124. )
  125. # >= 500
  126. tts500 = Mock()
  127. response500 = Mock(status_code=500, reason="ccc")
  128. error500 = gTTSError(tts=tts500, response=response500)
  129. assert (
  130. error500.msg
  131. == "500 (ccc) from TTS API. Probable cause: Upstream API error. Try again later."
  132. )
  133. # Unknown (ex. 100)
  134. tts100 = Mock()
  135. response100 = Mock(status_code=100, reason="ddd")
  136. error100 = gTTSError(tts=tts100, response=response100)
  137. assert error100.msg == "100 (ddd) from TTS API. Probable cause: Unknown"
  138. @pytest.mark.net
  139. def test_WebRequest(tmp_path):
  140. """Test Web Requests"""
  141. text = "Lorem ipsum"
  142. """Raise gTTSError on unsupported language (without language check)"""
  143. lang = "xx"
  144. check = False
  145. with pytest.raises(gTTSError):
  146. filename = tmp_path / "xx.txt"
  147. # Create gTTS
  148. tts = gTTS(text=text, lang=lang, lang_check=check)
  149. tts.save(filename)
  150. @pytest.mark.net
  151. def test_timeout(tmp_path):
  152. # Check default timeout
  153. tts = gTTS(text="test")
  154. assert tts.timeout is None
  155. # Check passed in timeout
  156. timeout = 1.2
  157. tts = gTTS(text="test", timeout=timeout)
  158. assert tts.timeout == timeout
  159. # Make sure an exception is raised when a timeout occurs
  160. tts = gTTS(text="test", timeout=0.000001)
  161. filename = tmp_path / "save.mp3"
  162. with pytest.raises(gTTSError):
  163. tts.save(filename)
  164. if __name__ == "__main__":
  165. pytest.main(["-x", __file__])