tests.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import, unicode_literals
  3. from django.forms import EmailField, IntegerField
  4. from django.http import HttpResponse
  5. from django.template.loader import render_to_string
  6. from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature
  7. from django.utils import six
  8. from django.utils.unittest import skip
  9. from .models import Person
  10. class SkippingTestCase(TestCase):
  11. def test_skip_unless_db_feature(self):
  12. "A test that might be skipped is actually called."
  13. # Total hack, but it works, just want an attribute that's always true.
  14. @skipUnlessDBFeature("__class__")
  15. def test_func():
  16. raise ValueError
  17. self.assertRaises(ValueError, test_func)
  18. class AssertNumQueriesTests(TestCase):
  19. urls = 'regressiontests.test_utils.urls'
  20. def test_assert_num_queries(self):
  21. def test_func():
  22. raise ValueError
  23. self.assertRaises(ValueError,
  24. self.assertNumQueries, 2, test_func
  25. )
  26. def test_assert_num_queries_with_client(self):
  27. person = Person.objects.create(name='test')
  28. self.assertNumQueries(
  29. 1,
  30. self.client.get,
  31. "/test_utils/get_person/%s/" % person.pk
  32. )
  33. self.assertNumQueries(
  34. 1,
  35. self.client.get,
  36. "/test_utils/get_person/%s/" % person.pk
  37. )
  38. def test_func():
  39. self.client.get("/test_utils/get_person/%s/" % person.pk)
  40. self.client.get("/test_utils/get_person/%s/" % person.pk)
  41. self.assertNumQueries(2, test_func)
  42. class AssertQuerysetEqualTests(TestCase):
  43. def setUp(self):
  44. self.p1 = Person.objects.create(name='p1')
  45. self.p2 = Person.objects.create(name='p2')
  46. def test_ordered(self):
  47. self.assertQuerysetEqual(
  48. Person.objects.all().order_by('name'),
  49. [repr(self.p1), repr(self.p2)]
  50. )
  51. def test_unordered(self):
  52. self.assertQuerysetEqual(
  53. Person.objects.all().order_by('name'),
  54. [repr(self.p2), repr(self.p1)],
  55. ordered=False
  56. )
  57. def test_transform(self):
  58. self.assertQuerysetEqual(
  59. Person.objects.all().order_by('name'),
  60. [self.p1.pk, self.p2.pk],
  61. transform=lambda x: x.pk
  62. )
  63. def test_undefined_order(self):
  64. # Using an unordered queryset with more than one ordered value
  65. # is an error.
  66. with self.assertRaises(ValueError):
  67. self.assertQuerysetEqual(
  68. Person.objects.all(),
  69. [repr(self.p1), repr(self.p2)]
  70. )
  71. # No error for one value.
  72. self.assertQuerysetEqual(
  73. Person.objects.filter(name='p1'),
  74. [repr(self.p1)]
  75. )
  76. class AssertNumQueriesContextManagerTests(TestCase):
  77. urls = 'regressiontests.test_utils.urls'
  78. def test_simple(self):
  79. with self.assertNumQueries(0):
  80. pass
  81. with self.assertNumQueries(1):
  82. Person.objects.count()
  83. with self.assertNumQueries(2):
  84. Person.objects.count()
  85. Person.objects.count()
  86. def test_failure(self):
  87. with self.assertRaises(AssertionError) as exc_info:
  88. with self.assertNumQueries(2):
  89. Person.objects.count()
  90. self.assertIn("1 queries executed, 2 expected", str(exc_info.exception))
  91. with self.assertRaises(TypeError):
  92. with self.assertNumQueries(4000):
  93. raise TypeError
  94. def test_with_client(self):
  95. person = Person.objects.create(name="test")
  96. with self.assertNumQueries(1):
  97. self.client.get("/test_utils/get_person/%s/" % person.pk)
  98. with self.assertNumQueries(1):
  99. self.client.get("/test_utils/get_person/%s/" % person.pk)
  100. with self.assertNumQueries(2):
  101. self.client.get("/test_utils/get_person/%s/" % person.pk)
  102. self.client.get("/test_utils/get_person/%s/" % person.pk)
  103. class AssertTemplateUsedContextManagerTests(TestCase):
  104. def test_usage(self):
  105. with self.assertTemplateUsed('template_used/base.html'):
  106. render_to_string('template_used/base.html')
  107. with self.assertTemplateUsed(template_name='template_used/base.html'):
  108. render_to_string('template_used/base.html')
  109. with self.assertTemplateUsed('template_used/base.html'):
  110. render_to_string('template_used/include.html')
  111. with self.assertTemplateUsed('template_used/base.html'):
  112. render_to_string('template_used/extends.html')
  113. with self.assertTemplateUsed('template_used/base.html'):
  114. render_to_string('template_used/base.html')
  115. render_to_string('template_used/base.html')
  116. def test_nested_usage(self):
  117. with self.assertTemplateUsed('template_used/base.html'):
  118. with self.assertTemplateUsed('template_used/include.html'):
  119. render_to_string('template_used/include.html')
  120. with self.assertTemplateUsed('template_used/extends.html'):
  121. with self.assertTemplateUsed('template_used/base.html'):
  122. render_to_string('template_used/extends.html')
  123. with self.assertTemplateUsed('template_used/base.html'):
  124. with self.assertTemplateUsed('template_used/alternative.html'):
  125. render_to_string('template_used/alternative.html')
  126. render_to_string('template_used/base.html')
  127. with self.assertTemplateUsed('template_used/base.html'):
  128. render_to_string('template_used/extends.html')
  129. with self.assertTemplateNotUsed('template_used/base.html'):
  130. render_to_string('template_used/alternative.html')
  131. render_to_string('template_used/base.html')
  132. def test_not_used(self):
  133. with self.assertTemplateNotUsed('template_used/base.html'):
  134. pass
  135. with self.assertTemplateNotUsed('template_used/alternative.html'):
  136. pass
  137. def test_error_message(self):
  138. with six.assertRaisesRegex(self, AssertionError, r'^template_used/base\.html'):
  139. with self.assertTemplateUsed('template_used/base.html'):
  140. pass
  141. with six.assertRaisesRegex(self, AssertionError, r'^template_used/base\.html'):
  142. with self.assertTemplateUsed(template_name='template_used/base.html'):
  143. pass
  144. with six.assertRaisesRegex(self, AssertionError, r'^template_used/base\.html.*template_used/alternative\.html$'):
  145. with self.assertTemplateUsed('template_used/base.html'):
  146. render_to_string('template_used/alternative.html')
  147. def test_failure(self):
  148. with self.assertRaises(TypeError):
  149. with self.assertTemplateUsed():
  150. pass
  151. with self.assertRaises(AssertionError):
  152. with self.assertTemplateUsed(''):
  153. pass
  154. with self.assertRaises(AssertionError):
  155. with self.assertTemplateUsed(''):
  156. render_to_string('template_used/base.html')
  157. with self.assertRaises(AssertionError):
  158. with self.assertTemplateUsed(template_name=''):
  159. pass
  160. with self.assertRaises(AssertionError):
  161. with self.assertTemplateUsed('template_used/base.html'):
  162. render_to_string('template_used/alternative.html')
  163. class SaveRestoreWarningState(TestCase):
  164. def test_save_restore_warnings_state(self):
  165. """
  166. Ensure save_warnings_state/restore_warnings_state work correctly.
  167. """
  168. # In reality this test could be satisfied by many broken implementations
  169. # of save_warnings_state/restore_warnings_state (e.g. just
  170. # warnings.resetwarnings()) , but it is difficult to test more.
  171. import warnings
  172. with warnings.catch_warnings():
  173. warnings.simplefilter("ignore", DeprecationWarning)
  174. self.save_warnings_state()
  175. class MyWarning(Warning):
  176. pass
  177. # Add a filter that causes an exception to be thrown, so we can catch it
  178. warnings.simplefilter("error", MyWarning)
  179. self.assertRaises(Warning, lambda: warnings.warn("warn", MyWarning))
  180. # Now restore.
  181. self.restore_warnings_state()
  182. # After restoring, we shouldn't get an exception. But we don't want a
  183. # warning printed either, so we have to silence the warning.
  184. warnings.simplefilter("ignore", MyWarning)
  185. warnings.warn("warn", MyWarning)
  186. # Remove the filter we just added.
  187. self.restore_warnings_state()
  188. class HTMLEqualTests(TestCase):
  189. def test_html_parser(self):
  190. from django.test.html import parse_html
  191. element = parse_html('<div><p>Hello</p></div>')
  192. self.assertEqual(len(element.children), 1)
  193. self.assertEqual(element.children[0].name, 'p')
  194. self.assertEqual(element.children[0].children[0], 'Hello')
  195. parse_html('<p>')
  196. parse_html('<p attr>')
  197. dom = parse_html('<p>foo')
  198. self.assertEqual(len(dom.children), 1)
  199. self.assertEqual(dom.name, 'p')
  200. self.assertEqual(dom[0], 'foo')
  201. def test_parse_html_in_script(self):
  202. from django.test.html import parse_html
  203. parse_html('<script>var a = "<p" + ">";</script>');
  204. parse_html('''
  205. <script>
  206. var js_sha_link='<p>***</p>';
  207. </script>
  208. ''')
  209. # script content will be parsed to text
  210. dom = parse_html('''
  211. <script><p>foo</p> '</scr'+'ipt>' <span>bar</span></script>
  212. ''')
  213. self.assertEqual(len(dom.children), 1)
  214. self.assertEqual(dom.children[0], "<p>foo</p> '</scr'+'ipt>' <span>bar</span>")
  215. def test_self_closing_tags(self):
  216. from django.test.html import parse_html
  217. self_closing_tags = ('br' , 'hr', 'input', 'img', 'meta', 'spacer',
  218. 'link', 'frame', 'base', 'col')
  219. for tag in self_closing_tags:
  220. dom = parse_html('<p>Hello <%s> world</p>' % tag)
  221. self.assertEqual(len(dom.children), 3)
  222. self.assertEqual(dom[0], 'Hello')
  223. self.assertEqual(dom[1].name, tag)
  224. self.assertEqual(dom[2], 'world')
  225. dom = parse_html('<p>Hello <%s /> world</p>' % tag)
  226. self.assertEqual(len(dom.children), 3)
  227. self.assertEqual(dom[0], 'Hello')
  228. self.assertEqual(dom[1].name, tag)
  229. self.assertEqual(dom[2], 'world')
  230. def test_simple_equal_html(self):
  231. self.assertHTMLEqual('', '')
  232. self.assertHTMLEqual('<p></p>', '<p></p>')
  233. self.assertHTMLEqual('<p></p>', ' <p> </p> ')
  234. self.assertHTMLEqual(
  235. '<div><p>Hello</p></div>',
  236. '<div><p>Hello</p></div>')
  237. self.assertHTMLEqual(
  238. '<div><p>Hello</p></div>',
  239. '<div> <p>Hello</p> </div>')
  240. self.assertHTMLEqual(
  241. '<div>\n<p>Hello</p></div>',
  242. '<div><p>Hello</p></div>\n')
  243. self.assertHTMLEqual(
  244. '<div><p>Hello\nWorld !</p></div>',
  245. '<div><p>Hello World\n!</p></div>')
  246. self.assertHTMLEqual(
  247. '<div><p>Hello\nWorld !</p></div>',
  248. '<div><p>Hello World\n!</p></div>')
  249. self.assertHTMLEqual(
  250. '<p>Hello World !</p>',
  251. '<p>Hello World\n\n!</p>')
  252. self.assertHTMLEqual('<p> </p>', '<p></p>')
  253. self.assertHTMLEqual('<p/>', '<p></p>')
  254. self.assertHTMLEqual('<p />', '<p></p>')
  255. self.assertHTMLEqual('<input checked>', '<input checked="checked">')
  256. self.assertHTMLEqual('<p>Hello', '<p> Hello')
  257. self.assertHTMLEqual('<p>Hello</p>World', '<p>Hello</p> World')
  258. def test_ignore_comments(self):
  259. self.assertHTMLEqual(
  260. '<div>Hello<!-- this is a comment --> World!</div>',
  261. '<div>Hello World!</div>')
  262. def test_unequal_html(self):
  263. self.assertHTMLNotEqual('<p>Hello</p>', '<p>Hello!</p>')
  264. self.assertHTMLNotEqual('<p>foo&#20;bar</p>', '<p>foo&nbsp;bar</p>')
  265. self.assertHTMLNotEqual('<p>foo bar</p>', '<p>foo &nbsp;bar</p>')
  266. self.assertHTMLNotEqual('<p>foo nbsp</p>', '<p>foo &nbsp;</p>')
  267. self.assertHTMLNotEqual('<p>foo #20</p>', '<p>foo &#20;</p>')
  268. self.assertHTMLNotEqual(
  269. '<p><span>Hello</span><span>World</span></p>',
  270. '<p><span>Hello</span>World</p>')
  271. self.assertHTMLNotEqual(
  272. '<p><span>Hello</span>World</p>',
  273. '<p><span>Hello</span><span>World</span></p>')
  274. def test_attributes(self):
  275. self.assertHTMLEqual(
  276. '<input type="text" id="id_name" />',
  277. '<input id="id_name" type="text" />')
  278. self.assertHTMLEqual(
  279. '''<input type='text' id="id_name" />''',
  280. '<input id="id_name" type="text" />')
  281. self.assertHTMLNotEqual(
  282. '<input type="text" id="id_name" />',
  283. '<input type="password" id="id_name" />')
  284. def test_complex_examples(self):
  285. self.assertHTMLEqual(
  286. """<tr><th><label for="id_first_name">First name:</label></th>
  287. <td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>
  288. <tr><th><label for="id_last_name">Last name:</label></th>
  289. <td><input type="text" id="id_last_name" name="last_name" value="Lennon" /></td></tr>
  290. <tr><th><label for="id_birthday">Birthday:</label></th>
  291. <td><input type="text" value="1940-10-9" name="birthday" id="id_birthday" /></td></tr>""",
  292. """
  293. <tr><th>
  294. <label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="John" id="id_first_name" />
  295. </td></tr>
  296. <tr><th>
  297. <label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="Lennon" id="id_last_name" />
  298. </td></tr>
  299. <tr><th>
  300. <label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" />
  301. </td></tr>
  302. """)
  303. self.assertHTMLEqual(
  304. """<!DOCTYPE html>
  305. <html>
  306. <head>
  307. <link rel="stylesheet">
  308. <title>Document</title>
  309. <meta attribute="value">
  310. </head>
  311. <body>
  312. <p>
  313. This is a valid paragraph
  314. <div> this is a div AFTER the p</div>
  315. </body>
  316. </html>""", """
  317. <html>
  318. <head>
  319. <link rel="stylesheet">
  320. <title>Document</title>
  321. <meta attribute="value">
  322. </head>
  323. <body>
  324. <p> This is a valid paragraph
  325. <!-- browsers would close the p tag here -->
  326. <div> this is a div AFTER the p</div>
  327. </p> <!-- this is invalid HTML parsing, but it should make no
  328. difference in most cases -->
  329. </body>
  330. </html>""")
  331. def test_html_contain(self):
  332. from django.test.html import parse_html
  333. # equal html contains each other
  334. dom1 = parse_html('<p>foo')
  335. dom2 = parse_html('<p>foo</p>')
  336. self.assertTrue(dom1 in dom2)
  337. self.assertTrue(dom2 in dom1)
  338. dom2 = parse_html('<div><p>foo</p></div>')
  339. self.assertTrue(dom1 in dom2)
  340. self.assertTrue(dom2 not in dom1)
  341. self.assertFalse('<p>foo</p>' in dom2)
  342. self.assertTrue('foo' in dom2)
  343. # when a root element is used ...
  344. dom1 = parse_html('<p>foo</p><p>bar</p>')
  345. dom2 = parse_html('<p>foo</p><p>bar</p>')
  346. self.assertTrue(dom1 in dom2)
  347. dom1 = parse_html('<p>foo</p>')
  348. self.assertTrue(dom1 in dom2)
  349. dom1 = parse_html('<p>bar</p>')
  350. self.assertTrue(dom1 in dom2)
  351. def test_count(self):
  352. from django.test.html import parse_html
  353. # equal html contains each other one time
  354. dom1 = parse_html('<p>foo')
  355. dom2 = parse_html('<p>foo</p>')
  356. self.assertEqual(dom1.count(dom2), 1)
  357. self.assertEqual(dom2.count(dom1), 1)
  358. dom2 = parse_html('<p>foo</p><p>bar</p>')
  359. self.assertEqual(dom2.count(dom1), 1)
  360. dom2 = parse_html('<p>foo foo</p><p>foo</p>')
  361. self.assertEqual(dom2.count('foo'), 3)
  362. dom2 = parse_html('<p class="bar">foo</p>')
  363. self.assertEqual(dom2.count('bar'), 0)
  364. self.assertEqual(dom2.count('class'), 0)
  365. self.assertEqual(dom2.count('p'), 0)
  366. self.assertEqual(dom2.count('o'), 2)
  367. dom2 = parse_html('<p>foo</p><p>foo</p>')
  368. self.assertEqual(dom2.count(dom1), 2)
  369. dom2 = parse_html('<div><p>foo<input type=""></p><p>foo</p></div>')
  370. self.assertEqual(dom2.count(dom1), 1)
  371. dom2 = parse_html('<div><div><p>foo</p></div></div>')
  372. self.assertEqual(dom2.count(dom1), 1)
  373. dom2 = parse_html('<p>foo<p>foo</p></p>')
  374. self.assertEqual(dom2.count(dom1), 1)
  375. dom2 = parse_html('<p>foo<p>bar</p></p>')
  376. self.assertEqual(dom2.count(dom1), 0)
  377. def test_parsing_errors(self):
  378. from django.test.html import HTMLParseError, parse_html
  379. with self.assertRaises(AssertionError):
  380. self.assertHTMLEqual('<p>', '')
  381. with self.assertRaises(AssertionError):
  382. self.assertHTMLEqual('', '<p>')
  383. with self.assertRaises(HTMLParseError):
  384. parse_html('</p>')
  385. def test_contains_html(self):
  386. response = HttpResponse('''<body>
  387. This is a form: <form action="" method="get">
  388. <input type="text" name="Hello" />
  389. </form></body>''')
  390. self.assertNotContains(response, "<input name='Hello' type='text'>")
  391. self.assertContains(response, '<form action="" method="get">')
  392. self.assertContains(response, "<input name='Hello' type='text'>", html=True)
  393. self.assertNotContains(response, '<form action="" method="get">', html=True)
  394. invalid_response = HttpResponse('''<body <bad>>''')
  395. with self.assertRaises(AssertionError):
  396. self.assertContains(invalid_response, '<p></p>')
  397. with self.assertRaises(AssertionError):
  398. self.assertContains(response, '<p "whats" that>')
  399. def test_unicode_handling(self):
  400. from django.http import HttpResponse
  401. response = HttpResponse('<p class="help">Some help text for the title (with unicode ŠĐĆŽćžšđ)</p>')
  402. self.assertContains(response, '<p class="help">Some help text for the title (with unicode ŠĐĆŽćžšđ)</p>', html=True)
  403. class XMLEqualTests(TestCase):
  404. def test_simple_equal(self):
  405. xml1 = "<elem attr1='a' attr2='b' />"
  406. xml2 = "<elem attr1='a' attr2='b' />"
  407. self.assertXMLEqual(xml1, xml2)
  408. def test_simple_equal_unordered(self):
  409. xml1 = "<elem attr1='a' attr2='b' />"
  410. xml2 = "<elem attr2='b' attr1='a' />"
  411. self.assertXMLEqual(xml1, xml2)
  412. def test_simple_equal_raise(self):
  413. xml1 = "<elem attr1='a' />"
  414. xml2 = "<elem attr2='b' attr1='a' />"
  415. with self.assertRaises(AssertionError):
  416. self.assertXMLEqual(xml1, xml2)
  417. def test_simple_not_equal(self):
  418. xml1 = "<elem attr1='a' attr2='c' />"
  419. xml2 = "<elem attr1='a' attr2='b' />"
  420. self.assertXMLNotEqual(xml1, xml2)
  421. def test_simple_not_equal_raise(self):
  422. xml1 = "<elem attr1='a' attr2='b' />"
  423. xml2 = "<elem attr2='b' attr1='a' />"
  424. with self.assertRaises(AssertionError):
  425. self.assertXMLNotEqual(xml1, xml2)
  426. def test_parsing_errors(self):
  427. xml_unvalid = "<elem attr1='a attr2='b' />"
  428. xml2 = "<elem attr2='b' attr1='a' />"
  429. with self.assertRaises(AssertionError):
  430. self.assertXMLNotEqual(xml_unvalid, xml2)
  431. def test_comment_root(self):
  432. xml1 = "<?xml version='1.0'?><!-- comment1 --><elem attr1='a' attr2='b' />"
  433. xml2 = "<?xml version='1.0'?><!-- comment2 --><elem attr2='b' attr1='a' />"
  434. self.assertXMLEqual(xml1, xml2)
  435. class SkippingExtraTests(TestCase):
  436. fixtures = ['should_not_be_loaded.json']
  437. # HACK: This depends on internals of our TestCase subclasses
  438. def __call__(self, result=None):
  439. # Detect fixture loading by counting SQL queries, should be zero
  440. with self.assertNumQueries(0):
  441. super(SkippingExtraTests, self).__call__(result)
  442. @skip("Fixture loading should not be performed for skipped tests.")
  443. def test_fixtures_are_skipped(self):
  444. pass
  445. class AssertRaisesMsgTest(SimpleTestCase):
  446. def test_special_re_chars(self):
  447. """assertRaisesMessage shouldn't interpret RE special chars."""
  448. def func1():
  449. raise ValueError("[.*x+]y?")
  450. self.assertRaisesMessage(ValueError, "[.*x+]y?", func1)
  451. class AssertFieldOutputTests(SimpleTestCase):
  452. def test_assert_field_output(self):
  453. error_invalid = ['Enter a valid email address.']
  454. self.assertFieldOutput(EmailField, {'a@a.com': 'a@a.com'}, {'aaa': error_invalid})
  455. self.assertRaises(AssertionError, self.assertFieldOutput, EmailField, {'a@a.com': 'a@a.com'}, {'aaa': error_invalid + ['Another error']})
  456. self.assertRaises(AssertionError, self.assertFieldOutput, EmailField, {'a@a.com': 'Wrong output'}, {'aaa': error_invalid})
  457. self.assertRaises(AssertionError, self.assertFieldOutput, EmailField, {'a@a.com': 'a@a.com'}, {'aaa': ['Come on, gimme some well formatted data, dude.']})
  458. def test_custom_required_message(self):
  459. class MyCustomField(IntegerField):
  460. default_error_messages = {
  461. 'required': 'This is really required.',
  462. }
  463. self.assertFieldOutput(MyCustomField, {}, {}, empty_value=None)
  464. __test__ = {"API_TEST": r"""
  465. # Some checks of the doctest output normalizer.
  466. # Standard doctests do fairly
  467. >>> import json
  468. >>> from django.utils.xmlutils import SimplerXMLGenerator
  469. >>> from django.utils.six import StringIO
  470. >>> def produce_json():
  471. ... return json.dumps(['foo', {'bar': ('baz', None, 1.0, 2), 'whiz': 42}])
  472. >>> def produce_xml():
  473. ... stream = StringIO()
  474. ... xml = SimplerXMLGenerator(stream, encoding='utf-8')
  475. ... xml.startDocument()
  476. ... xml.startElement("foo", {"aaa" : "1.0", "bbb": "2.0"})
  477. ... xml.startElement("bar", {"ccc" : "3.0"})
  478. ... xml.characters("Hello")
  479. ... xml.endElement("bar")
  480. ... xml.startElement("whiz", {})
  481. ... xml.characters("Goodbye")
  482. ... xml.endElement("whiz")
  483. ... xml.endElement("foo")
  484. ... xml.endDocument()
  485. ... return stream.getvalue()
  486. >>> def produce_xml_fragment():
  487. ... stream = StringIO()
  488. ... xml = SimplerXMLGenerator(stream, encoding='utf-8')
  489. ... xml.startElement("foo", {"aaa": "1.0", "bbb": "2.0"})
  490. ... xml.characters("Hello")
  491. ... xml.endElement("foo")
  492. ... xml.startElement("bar", {"ccc": "3.0", "ddd": "4.0"})
  493. ... xml.endElement("bar")
  494. ... return stream.getvalue()
  495. # JSON output is normalized for field order, so it doesn't matter
  496. # which order json dictionary attributes are listed in output
  497. >>> produce_json()
  498. '["foo", {"bar": ["baz", null, 1.0, 2], "whiz": 42}]'
  499. >>> produce_json()
  500. '["foo", {"whiz": 42, "bar": ["baz", null, 1.0, 2]}]'
  501. # XML output is normalized for attribute order, so it doesn't matter
  502. # which order XML element attributes are listed in output
  503. >>> produce_xml()
  504. '<?xml version="1.0" encoding="UTF-8"?>\n<foo aaa="1.0" bbb="2.0"><bar ccc="3.0">Hello</bar><whiz>Goodbye</whiz></foo>'
  505. >>> produce_xml()
  506. '<?xml version="1.0" encoding="UTF-8"?>\n<foo bbb="2.0" aaa="1.0"><bar ccc="3.0">Hello</bar><whiz>Goodbye</whiz></foo>'
  507. >>> produce_xml_fragment()
  508. '<foo aaa="1.0" bbb="2.0">Hello</foo><bar ccc="3.0" ddd="4.0"></bar>'
  509. >>> produce_xml_fragment()
  510. '<foo bbb="2.0" aaa="1.0">Hello</foo><bar ddd="4.0" ccc="3.0"></bar>'
  511. """}
  512. if not six.PY3:
  513. __test__["API_TEST"] += """
  514. >>> def produce_long():
  515. ... return 42L
  516. >>> def produce_int():
  517. ... return 42
  518. # Long values are normalized and are comparable to normal integers ...
  519. >>> produce_long()
  520. 42
  521. # ... and vice versa
  522. >>> produce_int()
  523. 42L
  524. """