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