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
31 def test_global_option_defaults():
32 """dictionary of programming languages and extensions"""
33 for ext
in [".py", ".sl", ".c"]:
34 assert ext
in defaults
.code_extensions
35 assert defaults
.languages
[".py"] == "python"
36 assert defaults
.languages
[".sl"] == "slang"
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 # default should appear in options
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_get_outfile_name(self
):
119 """should return a sensible outfile name given an infile name"""
120 # return stdout for stdin
121 values
= OptionValues({"infile": "-"})
122 values
.complete(**defaults
.__dict
__)
123 assert "-" == self
.options
._get
_outfile
_name
(values
)
124 # return with ".txt" stripped
125 values
= OptionValues({"infile": "foo.py.txt"})
126 values
.complete(**defaults
.__dict
__)
127 assert "foo.py" == self
.options
._get
_outfile
_name
(values
)
128 # return with ".txt" added if extension marks code file
129 values
= OptionValues({"infile": "foo.py"})
130 values
.complete(**defaults
.__dict
__)
131 assert "foo.py.txt" == self
.options
._get
_outfile
_name
(values
)
132 values
= OptionValues({"infile": "foo.sl"})
133 values
.complete(**defaults
.__dict
__)
134 assert "foo.sl.txt" == self
.options
._get
_outfile
_name
(values
)
135 values
= OptionValues({"infile": "foo.c"})
136 values
.complete(**defaults
.__dict
__)
137 assert "foo.c.txt" == self
.options
._get
_outfile
_name
(values
)
138 # return with ".txt" added if txt2code == False (not None!)
139 values
= OptionValues({"infile": "foo.py", "txt2code": False})
140 values
.complete(**defaults
.__dict
__)
141 assert "foo.py.txt" == self
.options
._get
_outfile
_name
(values
)
142 # catchall: add ".out" if no other guess possible
143 values
= OptionValues({"infile": "foo", "txt2code": None})
144 values
.complete(**defaults
.__dict
__)
145 assert "foo.out" == self
.options
._get
_outfile
_name
(values
)
147 def test_complete_values(self
):
148 """Basic test of the option completion"""
149 values
= OptionValues()
150 values
.infile
= "foo"
151 values
= self
.options
.complete_values(values
)
152 # the following options should be set:
153 print values
.infile
# logo, as we give it...
155 assert values
.outfile
== "foo.out" # fallback extension .out added
156 print values
.txt2code
157 assert values
.txt2code
== True # the default
158 print values
.language
159 assert values
.language
== "python" # the default
161 def test_complete_values_txt(self
):
162 """Test the option completion with a text input file"""
163 values
= OptionValues()
164 values
.infile
= "foo.txt"
165 values
= self
.options
.complete_values(values
)
166 # should set outfile (see also `test_get_outfile_name`)
167 assert values
.outfile
== "foo"
168 # should set conversion direction according to extension
169 assert values
.txt2code
== True
171 def test_complete_values_code(self
):
172 """Test the option completion with a code input file"""
173 values
= OptionValues()
174 values
.infile
= "foo.py"
175 values
= self
.options
.complete_values(values
)
176 # should set outfile name
177 assert values
.outfile
== "foo.py.txt"
178 # should set conversion directions according to extension
179 print values
.txt2code
180 assert values
.txt2code
== False, "set conversion according to extension"
182 def test_complete_values_dont_overwrite(self
):
183 """The option completion must not overwrite existing option values"""
184 values
= OptionValues()
185 values
.infile
= "foo.py"
186 values
.outfile
= "bar.txt"
187 values
.txt2code
= True
188 values
= self
.options
.complete_values(values
)
190 assert values
.outfile
== "bar.txt"
191 assert values
.txt2code
== True
193 def test_complete_values_language_infile(self
):
194 """set the language from the infile extension"""
195 values
= OptionValues()
196 values
.infile
= "foo.c"
197 values
= self
.options
.complete_values(values
)
199 assert values
.language
== "c++"
201 def test_complete_values_language_outfile(self
):
202 """set the language from the outfile extension"""
203 values
= OptionValues()
204 values
.outfile
= "foo.sl"
205 values
= self
.options
.complete_values(values
)
207 assert values
.language
== "slang"
209 def test_complete_values_language_fallback(self
):
210 """set the language from the fallback language"""
211 values
= OptionValues()
212 values
= self
.options
.complete_values(values
)
214 print "fallback language:", defaults
.fallback_language
215 assert values
.language
== defaults
.fallback_language
218 values
= self
.options(["--txt2code", "foo.sl"], txt2code
=False)
220 assert values
.txt2code
== True
221 assert values
.infile
== "foo.sl"
223 def test_call_language(self
):
224 """test the language setting from filename"""
225 values
= self
.options(["foo.sl"])
227 assert values
.language
== "slang"
229 def test_call_language_outfile(self
):
230 """test the language setting from filename"""
231 values
= self
.options(["foo, foo.sl"])
233 assert values
.language
== "slang"
235 ## Input and Output streams
236 ## ------------------------
241 """base class for IO tests, sets up and tears down example files in /tmp
243 txtpath
= "/tmp/pylit_test.py.txt"
244 codepath
= "/tmp/pylit_test.py"
245 outpath
= "/tmp/pylit_test.out"
248 """Set up the test files"""
249 txtfile
= file(self
.txtpath
, 'w')
251 # txtfile.flush() # is this needed if we close?
254 codefile
= file(self
.codepath
, 'w')
256 # codefile.flush() # is this needed if we close?
260 """clean up after all member tests are done"""
262 os
.unlink(self
.txtpath
)
263 os
.unlink(self
.codepath
)
264 os
.unlink(self
.outpath
)
268 class test_Streams(IOTests
):
269 def test_is_newer(self
):
270 # this __file__ is older, than code file
271 print __file__
, os
.path
.getmtime(__file__
)
272 print self
.codepath
, os
.path
.getmtime(self
.codepath
)
274 assert is_newer(self
.codepath
, __file__
) is True, "file1 is newer"
275 assert is_newer(__file__
, self
.codepath
) is False, "file2 is newer"
276 assert is_newer(__file__
, "fffo") is True, "file2 doesnot exist"
277 assert is_newer("fflo", __file__
) is False, "file1 doesnot exist"
279 assert is_newer(__file__
, __file__
) is None, "equal is not newer"
280 assert is_newer("fflo", "fffo") is None, "no file exists -> equal"
282 def test_open_streams(self
):
283 # default should return stdin and -out:
284 (instream
, outstream
) = open_streams()
285 assert instream
is sys
.stdin
286 assert outstream
is sys
.stdout
288 # open input and output file
289 (instream
, outstream
) = open_streams(self
.txtpath
, self
.outpath
)
290 assert type(instream
) == file
291 assert type(outstream
) == file
292 # read something from the input
293 assert instream
.read() == text
294 # write something to the output
295 outstream
.write(text
)
296 # check the output, we have to flush first
298 outfile
= file(self
.outpath
, 'r')
299 assert outfile
.read() == text
301 def test_open_streams_no_infile(self
):
302 """should exit with usage info if no infile given"""
304 (instream
, outstream
) = open_streams("")
305 assert False, "should rise SystemExit"
309 ## Another convenience function that returns a converter instance::
311 def test_get_converter():
312 # with default or txt2code
313 converter
= get_converter(textdata
)
314 print converter
.__class
__
315 assert converter
.__class
__ == Text2Code
316 converter
= get_converter(textdata
, txt2code
=False)
317 assert converter
.__class
__ == Code2Text
319 # the run_doctest runs a doctest on the text version (as doc-string)
320 class test_Run_Doctest(IOTests
):
321 """Doctest should run on the text source"""
322 def test_doctest_txt2code(self
):
323 (failures
, tests
) = run_doctest(self
.txtpath
, txt2code
=True)
324 assert (failures
, tests
) == (0, 0)
325 def test_doctest_code2txt(self
):
326 (failures
, tests
) = run_doctest(self
.codepath
, txt2code
=False)
327 assert (failures
, tests
) == (0, 0)
329 ## The main() function is called if the script is run from the command line
333 class test_Main(IOTests
):
334 """test default operation from command line
336 def get_output(self
):
337 """read and return the content of the output file"""
338 outstream
= file(self
.outpath
, 'r')
339 return outstream
.read()
341 def test_text_to_code(self
):
342 """test conversion of text file to code file"""
343 main(infile
=self
.txtpath
, outfile
=self
.outpath
)
344 output
= self
.get_output()
346 assert output
== code
348 def test_text_to_code_strip(self
):
349 """test conversion of text file to stripped code file"""
350 main(infile
=self
.txtpath
, outfile
=self
.outpath
, strip
=True)
351 output
= self
.get_output()
353 assert output
== stripped_code
355 def test_main_code_to_text(self
):
356 """test conversion of code file to text file"""
357 main(infile
=self
.codepath
, outfile
=self
.outpath
)
358 output
= self
.get_output()
359 assert output
== text
361 def test_main_code_to_text_strip(self
):
362 """test conversion of code file to stripped text file"""
363 main(infile
=self
.codepath
, outfile
=self
.outpath
, strip
=True)
364 output
= self
.get_output()
365 assert output
== stripped_text
367 def test_main_diff(self
):
368 result
= main(infile
=self
.codepath
, diff
=True)
369 print "diff return value", result
370 assert result
is False # no differences found
372 def test_main_diff_with_differences(self
):
373 """diffing a file to itself should fail, as the input is converted"""
374 result
= main(infile
=self
.codepath
, outfile
=self
.codepath
, diff
=True)
375 print "diff return value", result
376 assert result
is True # differences found
378 def test_main_execute(self
):
379 result
= main(infile
=self
.txtpath
, execute
=True)
382 def test_main_execute_code(self
):
383 result
= main(infile
=self
.codepath
, execute
=True)
385 if __name__
== "__main__":
386 nose
.runmodule() # requires nose 0.9.1