/unit_tests/test_xunit.py
Python | 343 lines | 335 code | 8 blank | 0 comment | 5 complexity | b5aeb525449a60a794b3dc25ec95456c MD5 | raw file
1 2import sys 3import os 4import optparse 5import re 6import unittest 7from xml.sax import saxutils 8 9from nose.pyversion import UNICODE_STRINGS 10from nose.tools import eq_ 11from nose.plugins.xunit import Xunit, escape_cdata, id_split 12from nose.exc import SkipTest 13from nose.config import Config 14 15def mktest(): 16 class TC(unittest.TestCase): 17 def runTest(self): 18 pass 19 test = TC() 20 return test 21 22mktest.__test__ = False 23 24time_taken = re.compile(r'\d\.\d\d') 25 26class TestEscaping(unittest.TestCase): 27 28 def setUp(self): 29 self.x = Xunit() 30 31 def test_all(self): 32 eq_(self.x._quoteattr( 33 '''<baz src="http://foo?f=1&b=2" quote="inix hubris 'maximus'?" />'''), 34 ('"<baz src="http://foo?f=1&b=2" ' 35 'quote="inix hubris \'maximus\'?" />"')) 36 37 def test_unicode_is_utf8_by_default(self): 38 if not UNICODE_STRINGS: 39 eq_(self.x._quoteattr(u'Ivan Krsti\u0107'), 40 '"Ivan Krsti\xc4\x87"') 41 42 def test_unicode_custom_utf16_madness(self): 43 self.x.encoding = 'utf-16' 44 utf16 = self.x._quoteattr(u'Ivan Krsti\u0107')[1:-1] 45 46 if UNICODE_STRINGS: 47 # If all internal strings are unicode, then _quoteattr shouldn't 48 # have changed anything. 49 eq_(utf16, u'Ivan Krsti\u0107') 50 else: 51 # to avoid big/little endian bytes, assert that we can put it back: 52 eq_(utf16.decode('utf16'), u'Ivan Krsti\u0107') 53 54 def test_control_characters(self): 55 # quoting of \n, \r varies in diff. python versions 56 n = saxutils.quoteattr('\n')[1:-1] 57 r = saxutils.quoteattr('\r')[1:-1] 58 eq_(self.x._quoteattr('foo\n\b\f\r'), '"foo%s??%s"' % (n, r)) 59 eq_(escape_cdata('foo\n\b\f\r'), 'foo\n??\r') 60 61class TestSplitId(unittest.TestCase): 62 63 def check_id_split(self, cls, name): 64 split = id_split('%s.%s' % (cls, name)) 65 eq_(split[0], cls) 66 eq_(split[1], name) 67 68 def test_no_parenthesis(self): 69 self.check_id_split("test_parset", "test_args") 70 71 def test_no_dot_in_args(self): 72 self.check_id_split("test_parset", "test_args(('x', [1, 2]),)") 73 74 def test_dot_in_args(self): 75 self.check_id_split("test_parset", "test_args(('x.y', 1),)") 76 77 def test_grandchild_has_dot_in_args(self): 78 self.check_id_split("test_grandparset.test_parset", 79 "test_args(('x.y', 1),)") 80 81class TestOptions(unittest.TestCase): 82 83 def test_defaults(self): 84 parser = optparse.OptionParser() 85 x = Xunit() 86 x.add_options(parser, env={}) 87 (options, args) = parser.parse_args([]) 88 eq_(options.xunit_file, "nosetests.xml") 89 90 def test_file_from_environ(self): 91 parser = optparse.OptionParser() 92 x = Xunit() 93 x.add_options(parser, env={'NOSE_XUNIT_FILE': "kangaroo.xml"}) 94 (options, args) = parser.parse_args([]) 95 eq_(options.xunit_file, "kangaroo.xml") 96 97 def test_file_from_opt(self): 98 parser = optparse.OptionParser() 99 x = Xunit() 100 x.add_options(parser, env={}) 101 (options, args) = parser.parse_args(["--xunit-file=blagojevich.xml"]) 102 eq_(options.xunit_file, "blagojevich.xml") 103 104class TestXMLOutputWithXML(unittest.TestCase): 105 106 def setUp(self): 107 self.xmlfile = os.path.abspath( 108 os.path.join(os.path.dirname(__file__), 109 'support', 'xunit.xml')) 110 parser = optparse.OptionParser() 111 self.x = Xunit() 112 self.x.add_options(parser, env={}) 113 (options, args) = parser.parse_args([ 114 "--with-xunit", 115 "--xunit-file=%s" % self.xmlfile 116 ]) 117 self.x.configure(options, Config()) 118 119 try: 120 import xml.etree.ElementTree 121 except ImportError: 122 self.ET = False 123 else: 124 self.ET = xml.etree.ElementTree 125 126 def tearDown(self): 127 os.unlink(self.xmlfile) 128 129 def get_xml_report(self): 130 class DummyStream: 131 pass 132 self.x.report(DummyStream()) 133 f = open(self.xmlfile, 'rb') 134 return f.read() 135 f.close() 136 137 def test_addFailure(self): 138 test = mktest() 139 self.x.startTest(test) 140 try: 141 raise AssertionError("one is not 'equal' to two") 142 except AssertionError: 143 some_err = sys.exc_info() 144 145 self.x.addFailure(test, some_err) 146 147 result = self.get_xml_report() 148 print result 149 150 if self.ET: 151 tree = self.ET.fromstring(result) 152 eq_(tree.attrib['name'], "nosetests") 153 eq_(tree.attrib['tests'], "1") 154 eq_(tree.attrib['errors'], "0") 155 eq_(tree.attrib['failures'], "1") 156 eq_(tree.attrib['skip'], "0") 157 158 tc = tree.find("testcase") 159 eq_(tc.attrib['classname'], "test_xunit.TC") 160 eq_(tc.attrib['name'], "runTest") 161 assert time_taken.match(tc.attrib['time']), ( 162 'Expected decimal time: %s' % tc.attrib['time']) 163 164 err = tc.find("failure") 165 eq_(err.attrib['type'], "%s.AssertionError" % (AssertionError.__module__,)) 166 err_lines = err.text.strip().split("\n") 167 eq_(err_lines[0], 'Traceback (most recent call last):') 168 eq_(err_lines[-1], 'AssertionError: one is not \'equal\' to two') 169 eq_(err_lines[-2], ' raise AssertionError("one is not \'equal\' to two")') 170 else: 171 # this is a dumb test for 2.4- 172 assert '<?xml version="1.0" encoding="UTF-8"?>' in result 173 assert '<testsuite name="nosetests" tests="1" errors="0" failures="1" skip="0">' in result 174 assert '<testcase classname="test_xunit.TC" name="runTest"' in result 175 assert '<failure type="exceptions.AssertionError"' in result 176 assert "AssertionError: one is not 'equal' to two" in result 177 assert "AssertionError(\"one is not 'equal' to two\")" in result 178 assert '</failure></testcase></testsuite>' in result 179 180 def test_addFailure_early(self): 181 test = mktest() 182 try: 183 raise AssertionError("one is not equal to two") 184 except AssertionError: 185 some_err = sys.exc_info() 186 187 # add failure without startTest, due to custom TestResult munging? 188 self.x.addFailure(test, some_err) 189 190 result = self.get_xml_report() 191 print result 192 193 if self.ET: 194 tree = self.ET.fromstring(result) 195 tc = tree.find("testcase") 196 assert time_taken.match(tc.attrib['time']), ( 197 'Expected decimal time: %s' % tc.attrib['time']) 198 else: 199 # this is a dumb test for 2.4- 200 assert '<?xml version="1.0" encoding="UTF-8"?>' in result 201 assert ('<testcase classname="test_xunit.TC" ' 202 'name="runTest" time="0') in result 203 204 def test_addError(self): 205 test = mktest() 206 self.x.startTest(test) 207 try: 208 raise RuntimeError("some error happened") 209 except RuntimeError: 210 some_err = sys.exc_info() 211 212 self.x.addError(test, some_err) 213 214 result = self.get_xml_report() 215 print result 216 217 if self.ET: 218 tree = self.ET.fromstring(result) 219 eq_(tree.attrib['name'], "nosetests") 220 eq_(tree.attrib['tests'], "1") 221 eq_(tree.attrib['errors'], "1") 222 eq_(tree.attrib['failures'], "0") 223 eq_(tree.attrib['skip'], "0") 224 225 tc = tree.find("testcase") 226 eq_(tc.attrib['classname'], "test_xunit.TC") 227 eq_(tc.attrib['name'], "runTest") 228 assert time_taken.match(tc.attrib['time']), ( 229 'Expected decimal time: %s' % tc.attrib['time']) 230 231 err = tc.find("error") 232 eq_(err.attrib['type'], "%s.RuntimeError" % (RuntimeError.__module__,)) 233 err_lines = err.text.strip().split("\n") 234 eq_(err_lines[0], 'Traceback (most recent call last):') 235 eq_(err_lines[-1], 'RuntimeError: some error happened') 236 eq_(err_lines[-2], ' raise RuntimeError("some error happened")') 237 else: 238 # this is a dumb test for 2.4- 239 assert '<?xml version="1.0" encoding="UTF-8"?>' in result 240 assert '<testsuite name="nosetests" tests="1" errors="1" failures="0" skip="0">' in result 241 assert '<testcase classname="test_xunit.TC" name="runTest"' in result 242 assert '<error type="exceptions.RuntimeError"' in result 243 assert 'RuntimeError: some error happened' in result 244 assert '</error></testcase></testsuite>' in result 245 246 def test_non_utf8_error(self): 247 # See http://code.google.com/p/python-nose/issues/detail?id=395 248 test = mktest() 249 self.x.startTest(test) 250 try: 251 raise RuntimeError(chr(128)) # cannot encode as utf8 252 except RuntimeError: 253 some_err = sys.exc_info() 254 self.x.addError(test, some_err) 255 result = self.get_xml_report() 256 print repr(result) 257 if self.ET: 258 tree = self.ET.fromstring(result) 259 tc = tree.find("testcase") 260 err = tc.find("error") 261 if UNICODE_STRINGS: 262 eq_(err.attrib['message'], 263 '\x80') 264 else: 265 eq_(err.attrib['message'], 266 u'\ufffd') 267 else: 268 # this is a dumb test for 2.4- 269 assert 'RuntimeError: \xef\xbf\xbd' in result 270 271 def test_addError_early(self): 272 test = mktest() 273 try: 274 raise RuntimeError("some error happened") 275 except RuntimeError: 276 some_err = sys.exc_info() 277 278 # call addError without startTest 279 # which can happen if setup() raises an error 280 self.x.addError(test, some_err) 281 282 result = self.get_xml_report() 283 print result 284 285 if self.ET: 286 tree = self.ET.fromstring(result) 287 tc = tree.find("testcase") 288 assert time_taken.match(tc.attrib['time']), ( 289 'Expected decimal time: %s' % tc.attrib['time']) 290 else: 291 # this is a dumb test for 2.4- 292 assert '<?xml version="1.0" encoding="UTF-8"?>' in result 293 assert ('<testcase classname="test_xunit.TC" ' 294 'name="runTest" time="0') in result 295 296 def test_addSuccess(self): 297 test = mktest() 298 self.x.startTest(test) 299 self.x.addSuccess(test, (None,None,None)) 300 301 result = self.get_xml_report() 302 print result 303 304 if self.ET: 305 tree = self.ET.fromstring(result) 306 eq_(tree.attrib['name'], "nosetests") 307 eq_(tree.attrib['tests'], "1") 308 eq_(tree.attrib['errors'], "0") 309 eq_(tree.attrib['failures'], "0") 310 eq_(tree.attrib['skip'], "0") 311 312 tc = tree.find("testcase") 313 eq_(tc.attrib['classname'], "test_xunit.TC") 314 eq_(tc.attrib['name'], "runTest") 315 assert time_taken.match(tc.attrib['time']), ( 316 'Expected decimal time: %s' % tc.attrib['time']) 317 else: 318 # this is a dumb test for 2.4- 319 assert '<?xml version="1.0" encoding="UTF-8"?>' in result 320 assert '<testsuite name="nosetests" tests="1" errors="0" failures="0" skip="0">' in result 321 assert '<testcase classname="test_xunit.TC" name="runTest"' in result 322 assert '</testsuite>' in result 323 324 def test_addSuccess_early(self): 325 test = mktest() 326 # call addSuccess without startTest 327 # which can happen (?) -- did happen with JsLint plugin 328 self.x.addSuccess(test, (None,None,None)) 329 330 result = self.get_xml_report() 331 print result 332 333 if self.ET: 334 tree = self.ET.fromstring(result) 335 tc = tree.find("testcase") 336 assert time_taken.match(tc.attrib['time']), ( 337 'Expected decimal time: %s' % tc.attrib['time']) 338 else: 339 # this is a dumb test for 2.4- 340 assert '<?xml version="1.0" encoding="UTF-8"?>' in result 341 assert ('<testcase classname="test_xunit.TC" ' 342 'name="runTest" time="0') in result 343