1# -*- coding: utf-8 -*- 2import pytest 3import re 4import os 5from click.testing import CliRunner 6from gtts.cli import tts_cli 7 8# Need to look into gTTS' log output to test proper instantiation 9# - Use testfixtures.LogCapture() b/c TestCase.assertLogs() needs py3.4+ 10# - Clear 'gtts' logger handlers (set in gtts.cli) to reduce test noise 11import logging 12from testfixtures import LogCapture 13logger = logging.getLogger('gtts') 14logger.handlers = [] 15 16 17"""Test options and arguments""" 18 19 20def runner(args, input=None): 21 return CliRunner().invoke(tts_cli, args, input) 22 23 24def runner_debug(args, input=None): 25 return CliRunner().invoke(tts_cli, args + ['--debug'], input) 26 27 28# <text> tests 29def test_text_no_text_or_file(): 30 """One of <test> (arg) and <file> <opt> should be set""" 31 result = runner_debug([]) 32 33 assert "<file> required" in result.output 34 assert result.exit_code != 0 35 36 37def test_text_text_and_file(tmp_path): 38 """<test> (arg) and <file> <opt> should not be set together""" 39 filename = tmp_path / 'test_and_file.txt' 40 filename.touch() 41 42 result = runner_debug(['--file', str(filename), 'test']) 43 44 assert "<file> can't be used together" in result.output 45 assert result.exit_code != 0 46 47 48def test_text_empty(tmp_path): 49 """Exit on no text to speak (via <file>)""" 50 filename = tmp_path / 'text_empty.txt' 51 filename.touch() 52 53 result = runner_debug(['--file', str(filename)]) 54 55 assert "No text to speak" in result.output 56 assert result.exit_code != 0 57 58 59# <file> tests 60def test_file_not_exists(): 61 """<file> should exist""" 62 result = runner_debug(['--file', 'notexist.txt', 'test']) 63 64 assert "No such file or directory" in result.output 65 assert result.exit_code != 0 66 67 68# <all> tests 69@pytest.mark.net 70def test_all(): 71 """Option <all> should return a list of languages""" 72 result = runner(['--all']) 73 74 # One or more of " xy: name" (\n optional to match the last) 75 # Ex. "<start> xx: xxxxx\n xx-yy: xxxxx\n xx: xxxxx<end>" 76 77 assert re.match(r"^(?:\s{2}(\w{2}|\w{2}-\w{2}): .+\n?)+$", result.output) 78 assert result.exit_code == 0 79 80 81# <lang> tests 82@pytest.mark.net 83def test_lang_not_valid(): 84 """Invalid <lang> should display an error""" 85 result = runner(['--lang', 'xx', 'test']) 86 87 assert "xx' not in list of supported languages" in result.output 88 assert result.exit_code != 0 89 90 91@pytest.mark.net 92def test_lang_nocheck(): 93 """Invalid <lang> (with <nocheck>) should display an error message from gtts""" 94 with LogCapture() as lc: 95 result = runner_debug(['--lang', 'xx', '--nocheck', 'test']) 96 97 log = str(lc) 98 99 assert 'lang: xx' in log 100 assert 'lang_check: False' in log 101 assert "Unsupported language 'xx'" in result.output 102 assert result.exit_code != 0 103 104# Param set tests 105@pytest.mark.net 106def test_params_set(): 107 """Options should set gTTS instance arguments (read from debug log)""" 108 with LogCapture() as lc: 109 result = runner_debug(['--lang', 'fr', '--tld', 'es', '--slow', '--nocheck', 'test']) 110 111 log = str(lc) 112 113 assert 'lang: fr' in log 114 assert 'tld: es' in log 115 assert 'lang_check: False' in log 116 assert 'slow: True' in log 117 assert 'text: test' in log 118 assert result.exit_code == 0 119 120 121# Test all input methods 122pwd = os.path.dirname(__file__) 123 124# Text for stdin ('-' for <text> or <file>) 125textstdin = """stdin 126test 127123""" 128 129# Text for stdin ('-' for <text> or <file>) (Unicode) 130textstdin_unicode = u"""你吃饭了吗? 131你最喜欢哪部电影? 132我饿了,我要去做饭了。""" 133 134# Text for <text> and <file> 135text = """Can you make pink a little more pinkish can you make pink a little more pinkish, nor can you make the font bigger? 136How much will it cost the website doesn't have the theme i was going for.""" 137 138textfile_ascii = os.path.join(pwd, 'input_files', 'test_cli_test_ascii.txt') 139 140# Text for <text> and <file> (Unicode) 141text_unicode = u"""这是一个三岁的小孩 142在讲述她从一系列照片里看到的东西。 143对这个世界, 她也许还有很多要学的东西, 144但在一个重要的任务上, 她已经是专家了: 145去理解她所看到的东西。""" 146 147textfile_utf8 = os.path.join(pwd, 'input_files', 'test_cli_test_utf8.txt') 148 149""" 150Method that mimics's LogCapture's __str__ method to make 151the string in the comprehension a unicode literal for P2.7 152https://github.com/Simplistix/testfixtures/blob/32c87902cb111b7ede5a6abca9b597db551c88ef/testfixtures/logcapture.py#L149 153""" 154 155 156def logcapture_str(lc): 157 if not lc.records: 158 return 'No logging captured' 159 160 return '\n'.join([u"%s %s\n %s" % r for r in lc.actual()]) 161 162 163@pytest.mark.net 164def test_stdin_text(): 165 with LogCapture() as lc: 166 result = runner_debug(['-'], textstdin) 167 log = logcapture_str(lc) 168 169 assert 'text: %s' % textstdin in log 170 assert result.exit_code == 0 171 172 173@pytest.mark.net 174def test_stdin_text_unicode(): 175 with LogCapture() as lc: 176 result = runner_debug(['-'], textstdin_unicode) 177 log = logcapture_str(lc) 178 179 assert u'text: %s' % textstdin_unicode in log 180 assert result.exit_code == 0 181 182 183@pytest.mark.net 184def test_stdin_file(): 185 with LogCapture() as lc: 186 result = runner_debug(['--file', '-'], textstdin) 187 log = logcapture_str(lc) 188 189 assert 'text: %s' % textstdin in log 190 assert result.exit_code == 0 191 192 193@pytest.mark.net 194def test_stdin_file_unicode(): 195 with LogCapture() as lc: 196 result = runner_debug(['--file', '-'], textstdin_unicode) 197 log = logcapture_str(lc) 198 199 assert 'text: %s' % textstdin_unicode in log 200 assert result.exit_code == 0 201 202 203@pytest.mark.net 204def test_text(): 205 with LogCapture() as lc: 206 result = runner_debug([text]) 207 log = logcapture_str(lc) 208 209 assert "text: %s" % text in log 210 assert result.exit_code == 0 211 212 213@pytest.mark.net 214def test_text_unicode(): 215 with LogCapture() as lc: 216 result = runner_debug([text_unicode]) 217 log = logcapture_str(lc) 218 219 assert "text: %s" % text_unicode in log 220 assert result.exit_code == 0 221 222 223@pytest.mark.net 224def test_file_ascii(): 225 with LogCapture() as lc: 226 result = runner_debug(['--file', textfile_ascii]) 227 log = logcapture_str(lc) 228 229 assert "text: %s" % text in log 230 assert result.exit_code == 0 231 232 233@pytest.mark.net 234def test_file_utf8(): 235 with LogCapture() as lc: 236 result = runner_debug(['--file', textfile_utf8]) 237 log = logcapture_str(lc) 238 239 assert "text: %s" % text_unicode in log 240 assert result.exit_code == 0 241 242 243@pytest.mark.net 244def test_stdout(): 245 result = runner(['test']) 246 247 # The MP3 encoding (LAME 3.99.5) used to leave a signature in the raw output 248 # This no longer appears to be the case 249 assert result.exit_code == 0 250 251 252@pytest.mark.net 253def test_file(tmp_path): 254 filename = tmp_path / 'out.mp3' 255 256 result = runner(['test', '--output', str(filename)]) 257 258 # Check if files created is > 2k 259 assert filename.stat().st_size > 2000 260 assert result.exit_code == 0 261 262 263if __name__ == '__main__': 264 pytest.main(['-x', __file__]) 265