3 ## Test the pylit.py literal python module's user interface
4 ## ========================================================
6 ## :Date: $Date: 2007-05-17 $
7 ## :Version: SVN-Revision $Revision: 45 $
8 ## :URL: $URL: svn+ssh://svn.berlios.de/svnroot/repos/pylit/trunk/test/pylit_ui_test.py $
9 ## :Copyright: 2006 Guenter Milde.
10 ## Released under the terms of the GNU General Public License
17 """pylit_test.py: test the "literal python" module's user interface"""
21 from pprint
import pprint
24 from pylit_test
import (text
, stripped_text
, textdata
,
25 code
, stripped_code
, codedata
)
34 def test_global_option_defaults():
35 """dictionary of programming languages and extensions"""
36 assert defaults
.languages
[".py"] == "python"
37 assert defaults
.languages
[".sl"] == "slang"
38 assert defaults
.languages
[".cc"] == "c++"
39 assert defaults
.languages
[".c"] == "c"
45 ## Test the option parsing::
47 class test_PylitOptions
:
48 """Test the PylitOption class"""
50 self
.options
= PylitOptions()
52 def test_args_parsing(self
):
53 """parse cmd line args with `ArgumentParser.parse_args()`"""
54 # "1st non option arg is infile, 2nd is outfile"
55 values
= self
.options
.parser
.parse_args(["--txt2code", "text.txt", "code.py"])
57 assert values
.infile
== "text.txt"
58 assert values
.outfile
== "code.py"
59 # option with argument
60 values
= self
.options
.parser
.parse_args(['in.py', '--language', 'slang'])
61 assert values
.language
== "slang"
63 def test_args_comment_string(self
):
64 """command line arg should appear in values"""
65 values
= self
.options(['in.py', '--comment-string=% '])
67 assert values
.comment_string
== "% "
69 def test_args_code_block_marker(self
):
70 """command line option --code-block-marker should set option value"""
71 values
= self
.options(['in.py', '--code-block-marker=.. test-dir::'])
73 assert values
.code_block_marker
== '.. test-dir::'
75 def test_get_outfile_name(self
):
76 """should return a sensible outfile name given an infile name"""
77 # return stdout for stdin
78 values
= copy
.copy(defaults
)
80 assert "-" == self
.options
._get
_outfile
_name
(values
)
81 # return with ".txt" stripped
82 values
= copy
.copy(defaults
)
83 values
.infile
= 'foo.py.txt'
84 assert "foo.py" == self
.options
._get
_outfile
_name
(values
)
85 # return with ".txt" added if extension marks code file
86 values
= copy
.copy(defaults
)
87 values
.infile
= 'foo.py'
88 assert "foo.py.txt" == self
.options
._get
_outfile
_name
(values
)
89 values
= copy
.copy(defaults
)
90 values
.infile
= 'foo.sl'
91 assert "foo.sl.txt" == self
.options
._get
_outfile
_name
(values
)
92 values
= copy
.copy(defaults
)
93 values
.infile
= 'foo.c'
94 assert "foo.c.txt" == self
.options
._get
_outfile
_name
(values
)
95 # return with ".txt" added if txt2code == False (not None!)
96 values
= copy
.copy(defaults
)
97 values
.infile
= 'foo.py'
98 values
.txt2code
= False
99 assert "foo.py.txt" == self
.options
._get
_outfile
_name
(values
)
100 # catchall: add ".out" if no other guess possible
101 values
= copy
.copy(defaults
)
102 values
.infile
= 'foo'
103 values
.txt2code
= None
104 print(self
.options
._get
_outfile
_name
(values
))
105 assert "foo.out" == self
.options
._get
_outfile
_name
(values
)
107 def test_complete_values(self
):
108 """Basic test of the option completion"""
109 values
= copy
.copy(defaults
)
110 values
.infile
= "foo"
111 values
= self
.options
.complete_values(values
)
112 # the following options should be set:
113 print('txt2code after:', values
.txt2code
)
114 print(values
.outfile
)
115 assert values
.outfile
== "foo.out" # fallback extension .out added
116 print(values
.txt2code
)
117 assert values
.txt2code
== True # the default
118 print(values
.language
)
119 assert values
.language
== "python" # the default
121 def test_complete_values_txt(self
):
122 """Test the option completion with a text input file"""
123 values
= copy
.copy(defaults
)
124 values
.infile
= "foo.txt"
125 values
= self
.options
.complete_values(values
)
126 # should set outfile (see also `test_get_outfile_name`)
127 assert values
.outfile
== "foo"
128 # should set conversion direction according to extension
129 assert values
.txt2code
== True
131 def test_complete_values_code(self
):
132 """Test the option completion with a code input file"""
133 values
= copy
.copy(defaults
)
134 values
.infile
= "foo.py"
135 values
= self
.options
.complete_values(values
)
136 # should set outfile name
137 assert values
.outfile
== "foo.py.txt"
138 # should set conversion directions according to extension
139 print(values
.txt2code
)
140 assert values
.txt2code
== False, "set conversion according to extension"
142 def test_complete_values_dont_overwrite(self
):
143 """The option completion must not overwrite existing option values"""
144 values
= copy
.copy(defaults
)
145 values
.infile
= "foo.py"
146 values
.outfile
= "bar.txt"
147 values
.txt2code
= True
148 values
= self
.options
.complete_values(values
)
150 assert values
.outfile
== "bar.txt"
151 assert values
.txt2code
== True
153 def test_complete_values_language_infile(self
):
154 """set the language from the infile extension"""
155 values
= copy
.copy(defaults
)
156 values
.infile
= "foo.cc"
157 values
= self
.options
.complete_values(values
)
159 assert values
.language
== "c++"
161 def test_complete_values_language_outfile(self
):
162 """set the language from the outfile extension"""
163 values
= copy
.copy(defaults
)
164 values
.txt2code
= True
165 values
.infile
= 'in-file'
166 values
.outfile
= "foo.sl"
167 values
= self
.options
.complete_values(values
)
169 assert values
.language
== "slang"
171 def test_complete_values_language_fallback(self
):
172 """set the language from the fallback language"""
173 values
= copy
.copy(defaults
)
174 values
.infile
= 'in-file' # required
175 values
= self
.options
.complete_values(values
)
177 print("fallback language:", defaults
.languages
[''])
178 assert values
.language
== defaults
.languages
['']
181 # if setting is not specified, use fallback from module `defaults`
182 values
= self
.options(infile
='in-file')
183 assert values
.txt2code
== True
184 # default should appear in options
185 values
= self
.options(infile
='in-file', txt2code
=False)
186 # print(values, type(values), dir(values))
187 assert values
.txt2code
== False
188 # "cmd line arg should appear as option overwriting default"
189 values
= self
.options(["--txt2code", "foo.sl"], txt2code
=False)
191 assert values
.txt2code
== True
192 assert values
.infile
== "foo.sl"
193 # "cmd line arg should appear as option overwriting default"
194 values
= self
.options(['in-file', '--comment-string=% '],
196 assert values
.comment_string
== '% '
198 def test_call_language(self
):
199 """test the language setting from filename"""
200 values
= self
.options(["foo.sl"])
202 assert values
.language
== "slang"
204 def test_call_language_outfile(self
):
205 """test the language setting from filename"""
206 values
= self
.options(["foo, foo.sl"])
208 assert values
.language
== "slang"
210 ## Input and Output streams
211 ## ------------------------
216 """base class for IO tests, sets up and tears down example files in /tmp
218 txtpath
= "/tmp/pylit_test.py.txt"
219 codepath
= "/tmp/pylit_test.py"
220 outpath
= "/tmp/pylit_test.out"
223 """Set up the test files"""
224 txtfile
= open(self
.txtpath
, 'w')
226 # txtfile.flush() # is this needed if we close?
229 codefile
= open(self
.codepath
, 'w')
231 # codefile.flush() # is this needed if we close?
235 """clean up after all member tests are done"""
237 os
.unlink(self
.txtpath
)
238 os
.unlink(self
.codepath
)
239 os
.unlink(self
.outpath
)
243 def get_output(self
):
244 """read and return the content of the output file"""
245 with
open(self
.outpath
, 'r') as outstream
:
246 return outstream
.read()
250 class test_Streams(IOTests
):
251 def test_is_newer(self
):
252 # this __file__ is older, than code file
253 print(__file__
, os
.path
.getmtime(__file__
))
254 print(self
.codepath
, os
.path
.getmtime(self
.codepath
))
256 assert is_newer(self
.codepath
, __file__
) is True, "file1 is newer"
257 assert is_newer(__file__
, self
.codepath
) is False, "file2 is newer"
258 assert is_newer(__file__
, "fffo") is True, "file2 doesnot exist"
259 assert is_newer("fflo", __file__
) is False, "file1 doesnot exist"
261 assert is_newer(__file__
, __file__
) is None, "equal is not newer"
262 assert is_newer("fflo", "fffo") is None, "no file exists -> equal"
264 def test_open_streams(self
):
265 # default should return stdin and -out:
266 (instream
, outstream
) = open_streams()
267 assert instream
is sys
.stdin
268 assert outstream
is sys
.stdout
270 # open input and output file
271 (instream
, outstream
) = open_streams(self
.txtpath
, self
.outpath
)
272 print(type(instream
), type(outstream
))
273 assert type(instream
) == type(open(self
.txtpath
))
274 assert type(outstream
) == type(open(self
.outpath
))
275 # read something from the input
276 assert instream
.read() == text
277 # write something to the output
278 outstream
.write(text
)
279 # check the output, we have to flush first
281 outfile
= open(self
.outpath
, 'r')
282 assert outfile
.read() == text
284 def test_open_streams_no_infile(self
):
285 """should exit with usage info if no infile given"""
287 (instream
, outstream
) = open_streams("")
288 assert False, "should rise IOError"
295 ## Return "right" converter instance (Text2Code or Code2Text instance)::
297 def test_get_converter():
298 # with default or txt2code
299 converter
= get_converter(textdata
)
300 print(converter
.__class
__)
301 assert converter
.__class
__ == Text2Code
302 converter
= get_converter(textdata
, txt2code
=False)
303 assert converter
.__class
__ == Code2Text
305 # the run_doctest runs a doctest on the text version (as doc-string)
306 class test_Run_Doctest(IOTests
):
307 """Doctest should run on the text source"""
308 def test_doctest_txt2code(self
):
309 (failures
, tests
) = run_doctest(self
.txtpath
, txt2code
=True)
310 assert (failures
, tests
) == (0, 0)
311 def test_doctest_code2txt(self
):
312 (failures
, tests
) = run_doctest(self
.codepath
, txt2code
=False)
313 assert (failures
, tests
) == (0, 0)
315 ## The main() function is called if the script is run from the command line
319 class test_Main(IOTests
):
320 """test default operation from command line
322 def test_text_to_code(self
):
323 """test conversion of text file to code file"""
324 main(infile
=self
.txtpath
, outfile
=self
.outpath
)
325 output
= self
.get_output()
327 assert output
== code
329 def test_text_to_code_strip(self
):
330 """test conversion of text file to stripped code file"""
331 main(infile
=self
.txtpath
, outfile
=self
.outpath
, strip
=True)
332 output
= self
.get_output()
334 assert output
== stripped_code
336 def test_text_to_code_twice(self
):
337 """conversion should work a second time"""
338 main(infile
=self
.txtpath
, outfile
=self
.outpath
)
339 main(infile
=self
.txtpath
, outfile
=self
.outpath
, overwrite
='yes')
340 output
= self
.get_output()
342 assert output
== code
344 def test_code_to_text(self
):
345 """test conversion of code file to text file"""
346 main(infile
=self
.codepath
, outfile
=self
.outpath
)
347 output
= self
.get_output()
348 assert output
== text
350 def test_code_to_text_strip(self
):
351 """test conversion of code file to stripped text file"""
352 main(infile
=self
.codepath
, outfile
=self
.outpath
, strip
=True)
353 output
= self
.get_output()
354 assert output
== stripped_text
356 def test_code_to_text_twice(self
):
357 """conversion should work also a second time"""
358 main(infile
=self
.codepath
, outfile
=self
.outpath
)
359 main(infile
=self
.codepath
, outfile
=self
.outpath
, overwrite
='yes')
360 output
= self
.get_output()
361 assert output
== text
364 result
= main(infile
=self
.codepath
, diff
=True)
365 print("diff return value", result
)
366 assert result
is False # no differences found
368 def test_diff_with_differences(self
):
369 """diffing a file to itself should fail, as the input is converted"""
370 result
= main(infile
=self
.codepath
, outfile
=self
.codepath
, diff
=True)
371 print("diff return value", result
)
372 assert result
is True # differences found
374 def test_execute(self
):
375 result
= main(infile
=self
.txtpath
, execute
=True)
378 def test_execute_code(self
):
379 result
= main(infile
=self
.codepath
, execute
=True)
382 class test_Programmatic_Use(IOTests
):
383 """test various aspects of programmatic use"""
385 def test_conversion(self
):
386 (data
, out_stream
) = open_streams(self
.txtpath
)
387 print("data: %r"%data
)
388 print("out_stream: %r"%out
_stream
)
389 converter
= get_converter(data
)
391 print("output: %r"%lines
)
392 # lines = converter()
393 assert lines
== codedata
396 if __name__
== "__main__":
397 nose
.runmodule() # requires nose 0.9.1