2 # -*- coding: iso-8859-1 -*-
4 ## Test the pylit.py literal python module's user interface
5 ## ========================================================
7 ## :Date: $Date: 2007-05-17 $
8 ## :Version: SVN-Revision $Revision: 45 $
9 ## :URL: $URL: svn+ssh://svn.berlios.de/svnroot/repos/pylit/trunk/test/pylit_ui_test.py $
10 ## :Copyright: 2006 Guenter Milde.
11 ## Released under the terms of the GNU General Public License
18 """pylit_test.py: test the "literal python" module's user interface"""
20 from pprint
import pprint
22 from pylit_test
import (text
, stripped_text
, textdata
,
23 code
, stripped_code
, codedata
)
32 def test_global_option_defaults():
33 """dictionary of programming languages and extensions"""
34 assert defaults
.languages
[".py"] == "python"
35 assert defaults
.languages
[".sl"] == "slang"
36 assert defaults
.languages
[".cc"] == "c++"
37 assert defaults
.languages
[".c"] == "c"
43 ## Test the option parsing::
45 class test_OptionValues(object):
46 defaults
= {"a1": 1, "a2": False}
48 self
.values
= OptionValues(self
.defaults
)
52 assert self
.values
.a1
== 1
53 assert self
.values
.a2
== False
55 def test_as_dict(self
):
56 print "as_dict() ->", self
.values
.as_dict()
57 assert self
.values
.as_dict() == self
.defaults
59 def test_complete(self
):
60 """complete should update non-existing values only"""
61 self
.values
.complete(**{"a1": 2, "a2": 4, "a3": 3})
62 print "completed ->", self
.values
63 assert self
.values
.a1
== 1, "must not overwrite existing value"
64 assert self
.values
.a2
== False, "must not overwrite existing value"
65 assert self
.values
.a3
== 3, "should set new attributes"
66 self
.values
.complete(a1
=2, a4
=20)
67 assert self
.values
.a1
== 1, "must not overwrite existing value"
68 assert self
.values
.a4
== 20, "should set new attributes"
70 def test_getattr(self
):
71 """Attempt to get a non-existing argument should return None
73 This make the code more concise as a try: except: AttributeError
74 statement or the parent class method `ensure_value(name, default)`.
76 assert self
.values
.a3
== None
78 def test_getattr_ensure_value(self
):
79 """Ensure value can be used to set a default different from None"""
80 assert self
.values
.a4
== None
81 self
.values
.ensure_value("a4", 32)
82 assert self
.values
.a4
== 32
85 class test_PylitOptions
:
86 """Test the PylitOption class"""
88 self
.options
= PylitOptions()
90 def test_parse_args(self
):
91 """parse cmd line args"""
92 # default should appear in options
93 values
= self
.options
.parse_args(txt2code
=False)
94 # print values, type(values), dir(values)
95 assert values
.txt2code
== False
96 # "cmd line arg should appear as option overwriting default"
97 values
= self
.options
.parse_args(["--txt2code"], txt2code
=False)
98 assert values
.txt2code
== True
99 # "1st non option arg is infile, 2nd is outfile"
100 values
= self
.options
.parse_args(["--txt2code", "text.txt", "code.py"])
102 assert values
.infile
== "text.txt"
103 assert values
.outfile
== "code.py"
104 # option with argument
105 values
= self
.options
.parse_args(["--language", "slang"])
106 assert values
.language
== "slang"
108 def test_parse_args_comment_string(self
):
109 # command line arg should appear in values
110 values
= self
.options
.parse_args(["--comment-string=% "])
111 pprint(values
.as_dict())
112 assert values
.comment_string
== "% "
113 # "cmd line arg should appear as option overwriting default"
114 values
= self
.options
.parse_args(["--comment-string=% "],
116 assert values
.comment_string
== '% '
118 def test_parse_args_code_block_marker(self
):
119 """command line option --code-block-marker should set option value"""
120 values
= self
.options
.parse_args(
121 ["--code-block-marker=.. test-dir::"])
122 pprint(values
.as_dict())
123 assert values
.code_block_marker
== '.. test-dir::'
125 def test_get_outfile_name(self
):
126 """should return a sensible outfile name given an infile name"""
127 # return stdout for stdin
128 values
= OptionValues({"infile": "-"})
129 values
.complete(**defaults
.__dict
__)
130 assert "-" == self
.options
._get
_outfile
_name
(values
)
131 # return with ".txt" stripped
132 values
= OptionValues({"infile": "foo.py.txt"})
133 values
.complete(**defaults
.__dict
__)
134 assert "foo.py" == self
.options
._get
_outfile
_name
(values
)
135 # return with ".txt" added if extension marks code file
136 values
= OptionValues({"infile": "foo.py"})
137 values
.complete(**defaults
.__dict
__)
138 assert "foo.py.txt" == self
.options
._get
_outfile
_name
(values
)
139 values
= OptionValues({"infile": "foo.sl"})
140 values
.complete(**defaults
.__dict
__)
141 assert "foo.sl.txt" == self
.options
._get
_outfile
_name
(values
)
142 values
= OptionValues({"infile": "foo.c"})
143 values
.complete(**defaults
.__dict
__)
144 assert "foo.c.txt" == self
.options
._get
_outfile
_name
(values
)
145 # return with ".txt" added if txt2code == False (not None!)
146 values
= OptionValues({"infile": "foo.py", "txt2code": False})
147 values
.complete(**defaults
.__dict
__)
148 assert "foo.py.txt" == self
.options
._get
_outfile
_name
(values
)
149 # catchall: add ".out" if no other guess possible
150 values
= OptionValues({"infile": "foo", "txt2code": None})
151 values
.complete(**defaults
.__dict
__)
152 assert "foo.out" == self
.options
._get
_outfile
_name
(values
)
154 def test_complete_values(self
):
155 """Basic test of the option completion"""
156 values
= OptionValues()
157 values
.infile
= "foo"
158 values
= self
.options
.complete_values(values
)
159 # the following options should be set:
160 print values
.infile
# logo, as we give it...
162 assert values
.outfile
== "foo.out" # fallback extension .out added
163 print values
.txt2code
164 assert values
.txt2code
== True # the default
165 print values
.language
166 assert values
.language
== "python" # the default
168 def test_complete_values_txt(self
):
169 """Test the option completion with a text input file"""
170 values
= OptionValues()
171 values
.infile
= "foo.txt"
172 values
= self
.options
.complete_values(values
)
173 # should set outfile (see also `test_get_outfile_name`)
174 assert values
.outfile
== "foo"
175 # should set conversion direction according to extension
176 assert values
.txt2code
== True
178 def test_complete_values_code(self
):
179 """Test the option completion with a code input file"""
180 values
= OptionValues()
181 values
.infile
= "foo.py"
182 values
= self
.options
.complete_values(values
)
183 # should set outfile name
184 assert values
.outfile
== "foo.py.txt"
185 # should set conversion directions according to extension
186 print values
.txt2code
187 assert values
.txt2code
== False, "set conversion according to extension"
189 def test_complete_values_dont_overwrite(self
):
190 """The option completion must not overwrite existing option values"""
191 values
= OptionValues()
192 values
.infile
= "foo.py"
193 values
.outfile
= "bar.txt"
194 values
.txt2code
= True
195 values
= self
.options
.complete_values(values
)
197 assert values
.outfile
== "bar.txt"
198 assert values
.txt2code
== True
200 def test_complete_values_language_infile(self
):
201 """set the language from the infile extension"""
202 values
= OptionValues()
203 values
.infile
= "foo.cc"
204 values
= self
.options
.complete_values(values
)
206 assert values
.language
== "c++"
208 def test_complete_values_language_outfile(self
):
209 """set the language from the outfile extension"""
210 values
= OptionValues()
211 values
.outfile
= "foo.sl"
212 values
= self
.options
.complete_values(values
)
214 assert values
.language
== "slang"
216 def test_complete_values_language_fallback(self
):
217 """set the language from the fallback language"""
218 values
= OptionValues()
219 values
= self
.options
.complete_values(values
)
221 print "fallback language:", defaults
.languages
.default
222 assert values
.language
== defaults
.languages
.default
225 values
= self
.options(["--txt2code", "foo.sl"], txt2code
=False)
227 assert values
.txt2code
== True
228 assert values
.infile
== "foo.sl"
230 def test_call_language(self
):
231 """test the language setting from filename"""
232 values
= self
.options(["foo.sl"])
234 assert values
.language
== "slang"
236 def test_call_language_outfile(self
):
237 """test the language setting from filename"""
238 values
= self
.options(["foo, foo.sl"])
240 assert values
.language
== "slang"
242 ## Input and Output streams
243 ## ------------------------
248 """base class for IO tests, sets up and tears down example files in /tmp
250 txtpath
= "/tmp/pylit_test.py.txt"
251 codepath
= "/tmp/pylit_test.py"
252 outpath
= "/tmp/pylit_test.out"
255 """Set up the test files"""
256 txtfile
= file(self
.txtpath
, 'w')
258 # txtfile.flush() # is this needed if we close?
261 codefile
= file(self
.codepath
, 'w')
263 # codefile.flush() # is this needed if we close?
267 """clean up after all member tests are done"""
269 os
.unlink(self
.txtpath
)
270 os
.unlink(self
.codepath
)
271 os
.unlink(self
.outpath
)
275 def get_output(self
):
276 """read and return the content of the output file"""
277 outstream
= file(self
.outpath
, 'r')
278 return outstream
.read()
282 class test_Streams(IOTests
):
283 def test_is_newer(self
):
284 # this __file__ is older, than code file
285 print __file__
, os
.path
.getmtime(__file__
)
286 print self
.codepath
, os
.path
.getmtime(self
.codepath
)
288 assert is_newer(self
.codepath
, __file__
) is True, "file1 is newer"
289 assert is_newer(__file__
, self
.codepath
) is False, "file2 is newer"
290 assert is_newer(__file__
, "fffo") is True, "file2 doesnot exist"
291 assert is_newer("fflo", __file__
) is False, "file1 doesnot exist"
293 assert is_newer(__file__
, __file__
) is None, "equal is not newer"
294 assert is_newer("fflo", "fffo") is None, "no file exists -> equal"
296 def test_open_streams(self
):
297 # default should return stdin and -out:
298 (instream
, outstream
) = open_streams()
299 assert instream
is sys
.stdin
300 assert outstream
is sys
.stdout
302 # open input and output file
303 (instream
, outstream
) = open_streams(self
.txtpath
, self
.outpath
)
304 assert type(instream
) == file
305 assert type(outstream
) == file
306 # read something from the input
307 assert instream
.read() == text
308 # write something to the output
309 outstream
.write(text
)
310 # check the output, we have to flush first
312 outfile
= file(self
.outpath
, 'r')
313 assert outfile
.read() == text
315 def test_open_streams_no_infile(self
):
316 """should exit with usage info if no infile given"""
318 (instream
, outstream
) = open_streams("")
319 assert False, "should rise IOError"
326 ## Return "right" converter instance (Text2Code or Code2Text instance)::
328 def test_get_converter():
329 # with default or txt2code
330 converter
= get_converter(textdata
)
331 print converter
.__class
__
332 assert converter
.__class
__ == Text2Code
333 converter
= get_converter(textdata
, txt2code
=False)
334 assert converter
.__class
__ == Code2Text
336 # the run_doctest runs a doctest on the text version (as doc-string)
337 class test_Run_Doctest(IOTests
):
338 """Doctest should run on the text source"""
339 def test_doctest_txt2code(self
):
340 (failures
, tests
) = run_doctest(self
.txtpath
, txt2code
=True)
341 assert (failures
, tests
) == (0, 0)
342 def test_doctest_code2txt(self
):
343 (failures
, tests
) = run_doctest(self
.codepath
, txt2code
=False)
344 assert (failures
, tests
) == (0, 0)
346 ## The main() function is called if the script is run from the command line
350 class test_Main(IOTests
):
351 """test default operation from command line
353 def test_text_to_code(self
):
354 """test conversion of text file to code file"""
355 main(infile
=self
.txtpath
, outfile
=self
.outpath
)
356 output
= self
.get_output()
358 assert output
== code
360 def test_text_to_code_strip(self
):
361 """test conversion of text file to stripped code file"""
362 main(infile
=self
.txtpath
, outfile
=self
.outpath
, strip
=True)
363 output
= self
.get_output()
365 assert output
== stripped_code
367 def test_text_to_code_twice(self
):
368 """conversion should work a second time"""
369 main(infile
=self
.txtpath
, outfile
=self
.outpath
)
370 main(infile
=self
.txtpath
, outfile
=self
.outpath
, overwrite
=True)
371 output
= self
.get_output()
373 assert output
== code
375 def test_code_to_text(self
):
376 """test conversion of code file to text file"""
377 main(infile
=self
.codepath
, outfile
=self
.outpath
)
378 output
= self
.get_output()
379 assert output
== text
381 def test_code_to_text_strip(self
):
382 """test conversion of code file to stripped text file"""
383 main(infile
=self
.codepath
, outfile
=self
.outpath
, strip
=True)
384 output
= self
.get_output()
385 assert output
== stripped_text
387 def test_code_to_text_twice(self
):
388 """conversion should work also a second time"""
389 main(infile
=self
.codepath
, outfile
=self
.outpath
)
390 main(infile
=self
.codepath
, outfile
=self
.outpath
)
391 output
= self
.get_output()
392 assert output
== text
395 result
= main(infile
=self
.codepath
, diff
=True)
396 print "diff return value", result
397 assert result
is False # no differences found
399 def test_diff_with_differences(self
):
400 """diffing a file to itself should fail, as the input is converted"""
401 result
= main(infile
=self
.codepath
, outfile
=self
.codepath
, diff
=True)
402 print "diff return value", result
403 assert result
is True # differences found
405 def test_execute(self
):
406 result
= main(infile
=self
.txtpath
, execute
=True)
409 def test_execute_code(self
):
410 result
= main(infile
=self
.codepath
, execute
=True)
413 class test_Programmatic_Use(IOTests
):
414 """test various aspects of programmatic use"""
416 def test_conversion(self
):
417 (data
, out_stream
) = open_streams(self
.txtpath
)
418 print "data: %r"%data
419 print "out_stream: %r"%out
_stream
420 converter
= get_converter(data
)
422 print "output: %r"%lines
423 # lines = converter()
424 assert lines
== codedata
427 if __name__
== "__main__":
428 nose
.runmodule() # requires nose 0.9.1