tests.py 82 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219
  1. import os
  2. import unittest
  3. import warnings
  4. from io import StringIO
  5. from unittest import mock
  6. from django.conf import STATICFILES_STORAGE_ALIAS, settings
  7. from django.contrib.staticfiles.finders import get_finder, get_finders
  8. from django.contrib.staticfiles.storage import staticfiles_storage
  9. from django.core.exceptions import ImproperlyConfigured
  10. from django.core.files.storage import default_storage
  11. from django.db import (
  12. IntegrityError,
  13. connection,
  14. connections,
  15. models,
  16. router,
  17. transaction,
  18. )
  19. from django.forms import (
  20. CharField,
  21. EmailField,
  22. Form,
  23. IntegerField,
  24. ValidationError,
  25. formset_factory,
  26. )
  27. from django.http import HttpResponse
  28. from django.template import Context, Template
  29. from django.template.loader import render_to_string
  30. from django.test import (
  31. SimpleTestCase,
  32. TestCase,
  33. TransactionTestCase,
  34. skipIfDBFeature,
  35. skipUnlessDBFeature,
  36. )
  37. from django.test.html import HTMLParseError, parse_html
  38. from django.test.testcases import DatabaseOperationForbidden
  39. from django.test.utils import (
  40. CaptureQueriesContext,
  41. TestContextDecorator,
  42. isolate_apps,
  43. override_settings,
  44. setup_test_environment,
  45. )
  46. from django.urls import NoReverseMatch, path, reverse, reverse_lazy
  47. from django.utils.html import VOID_ELEMENTS
  48. from django.utils.version import PY311
  49. from .models import Car, Person, PossessedCar
  50. from .views import empty_response
  51. class SkippingTestCase(SimpleTestCase):
  52. def _assert_skipping(self, func, expected_exc, msg=None):
  53. try:
  54. if msg is not None:
  55. with self.assertRaisesMessage(expected_exc, msg):
  56. func()
  57. else:
  58. with self.assertRaises(expected_exc):
  59. func()
  60. except unittest.SkipTest:
  61. self.fail("%s should not result in a skipped test." % func.__name__)
  62. def test_skip_unless_db_feature(self):
  63. """
  64. Testing the django.test.skipUnlessDBFeature decorator.
  65. """
  66. # Total hack, but it works, just want an attribute that's always true.
  67. @skipUnlessDBFeature("__class__")
  68. def test_func():
  69. raise ValueError
  70. @skipUnlessDBFeature("notprovided")
  71. def test_func2():
  72. raise ValueError
  73. @skipUnlessDBFeature("__class__", "__class__")
  74. def test_func3():
  75. raise ValueError
  76. @skipUnlessDBFeature("__class__", "notprovided")
  77. def test_func4():
  78. raise ValueError
  79. self._assert_skipping(test_func, ValueError)
  80. self._assert_skipping(test_func2, unittest.SkipTest)
  81. self._assert_skipping(test_func3, ValueError)
  82. self._assert_skipping(test_func4, unittest.SkipTest)
  83. class SkipTestCase(SimpleTestCase):
  84. @skipUnlessDBFeature("missing")
  85. def test_foo(self):
  86. pass
  87. self._assert_skipping(
  88. SkipTestCase("test_foo").test_foo,
  89. ValueError,
  90. "skipUnlessDBFeature cannot be used on test_foo (test_utils.tests."
  91. "SkippingTestCase.test_skip_unless_db_feature.<locals>.SkipTestCase%s) "
  92. "as SkippingTestCase.test_skip_unless_db_feature.<locals>.SkipTestCase "
  93. "doesn't allow queries against the 'default' database."
  94. # Python 3.11 uses fully qualified test name in the output.
  95. % (".test_foo" if PY311 else ""),
  96. )
  97. def test_skip_if_db_feature(self):
  98. """
  99. Testing the django.test.skipIfDBFeature decorator.
  100. """
  101. @skipIfDBFeature("__class__")
  102. def test_func():
  103. raise ValueError
  104. @skipIfDBFeature("notprovided")
  105. def test_func2():
  106. raise ValueError
  107. @skipIfDBFeature("__class__", "__class__")
  108. def test_func3():
  109. raise ValueError
  110. @skipIfDBFeature("__class__", "notprovided")
  111. def test_func4():
  112. raise ValueError
  113. @skipIfDBFeature("notprovided", "notprovided")
  114. def test_func5():
  115. raise ValueError
  116. self._assert_skipping(test_func, unittest.SkipTest)
  117. self._assert_skipping(test_func2, ValueError)
  118. self._assert_skipping(test_func3, unittest.SkipTest)
  119. self._assert_skipping(test_func4, unittest.SkipTest)
  120. self._assert_skipping(test_func5, ValueError)
  121. class SkipTestCase(SimpleTestCase):
  122. @skipIfDBFeature("missing")
  123. def test_foo(self):
  124. pass
  125. self._assert_skipping(
  126. SkipTestCase("test_foo").test_foo,
  127. ValueError,
  128. "skipIfDBFeature cannot be used on test_foo (test_utils.tests."
  129. "SkippingTestCase.test_skip_if_db_feature.<locals>.SkipTestCase%s) "
  130. "as SkippingTestCase.test_skip_if_db_feature.<locals>.SkipTestCase "
  131. "doesn't allow queries against the 'default' database."
  132. # Python 3.11 uses fully qualified test name in the output.
  133. % (".test_foo" if PY311 else ""),
  134. )
  135. class SkippingClassTestCase(TestCase):
  136. def test_skip_class_unless_db_feature(self):
  137. @skipUnlessDBFeature("__class__")
  138. class NotSkippedTests(TestCase):
  139. def test_dummy(self):
  140. return
  141. @skipUnlessDBFeature("missing")
  142. @skipIfDBFeature("__class__")
  143. class SkippedTests(TestCase):
  144. def test_will_be_skipped(self):
  145. self.fail("We should never arrive here.")
  146. @skipIfDBFeature("__dict__")
  147. class SkippedTestsSubclass(SkippedTests):
  148. pass
  149. test_suite = unittest.TestSuite()
  150. test_suite.addTest(NotSkippedTests("test_dummy"))
  151. try:
  152. test_suite.addTest(SkippedTests("test_will_be_skipped"))
  153. test_suite.addTest(SkippedTestsSubclass("test_will_be_skipped"))
  154. except unittest.SkipTest:
  155. self.fail("SkipTest should not be raised here.")
  156. result = unittest.TextTestRunner(stream=StringIO()).run(test_suite)
  157. self.assertEqual(result.testsRun, 3)
  158. self.assertEqual(len(result.skipped), 2)
  159. self.assertEqual(result.skipped[0][1], "Database has feature(s) __class__")
  160. self.assertEqual(result.skipped[1][1], "Database has feature(s) __class__")
  161. def test_missing_default_databases(self):
  162. @skipIfDBFeature("missing")
  163. class MissingDatabases(SimpleTestCase):
  164. def test_assertion_error(self):
  165. pass
  166. suite = unittest.TestSuite()
  167. try:
  168. suite.addTest(MissingDatabases("test_assertion_error"))
  169. except unittest.SkipTest:
  170. self.fail("SkipTest should not be raised at this stage")
  171. runner = unittest.TextTestRunner(stream=StringIO())
  172. msg = (
  173. "skipIfDBFeature cannot be used on <class 'test_utils.tests."
  174. "SkippingClassTestCase.test_missing_default_databases.<locals>."
  175. "MissingDatabases'> as it doesn't allow queries against the "
  176. "'default' database."
  177. )
  178. with self.assertRaisesMessage(ValueError, msg):
  179. runner.run(suite)
  180. @override_settings(ROOT_URLCONF="test_utils.urls")
  181. class AssertNumQueriesTests(TestCase):
  182. def test_assert_num_queries(self):
  183. def test_func():
  184. raise ValueError
  185. with self.assertRaises(ValueError):
  186. self.assertNumQueries(2, test_func)
  187. def test_assert_num_queries_with_client(self):
  188. person = Person.objects.create(name="test")
  189. self.assertNumQueries(
  190. 1, self.client.get, "/test_utils/get_person/%s/" % person.pk
  191. )
  192. self.assertNumQueries(
  193. 1, self.client.get, "/test_utils/get_person/%s/" % person.pk
  194. )
  195. def test_func():
  196. self.client.get("/test_utils/get_person/%s/" % person.pk)
  197. self.client.get("/test_utils/get_person/%s/" % person.pk)
  198. self.assertNumQueries(2, test_func)
  199. class AssertNumQueriesUponConnectionTests(TransactionTestCase):
  200. available_apps = []
  201. def test_ignores_connection_configuration_queries(self):
  202. real_ensure_connection = connection.ensure_connection
  203. connection.close()
  204. def make_configuration_query():
  205. is_opening_connection = connection.connection is None
  206. real_ensure_connection()
  207. if is_opening_connection:
  208. # Avoid infinite recursion. Creating a cursor calls
  209. # ensure_connection() which is currently mocked by this method.
  210. with connection.cursor() as cursor:
  211. cursor.execute("SELECT 1" + connection.features.bare_select_suffix)
  212. ensure_connection = (
  213. "django.db.backends.base.base.BaseDatabaseWrapper.ensure_connection"
  214. )
  215. with mock.patch(ensure_connection, side_effect=make_configuration_query):
  216. with self.assertNumQueries(1):
  217. list(Car.objects.all())
  218. class AssertQuerySetEqualTests(TestCase):
  219. @classmethod
  220. def setUpTestData(cls):
  221. cls.p1 = Person.objects.create(name="p1")
  222. cls.p2 = Person.objects.create(name="p2")
  223. def test_empty(self):
  224. self.assertQuerySetEqual(Person.objects.filter(name="p3"), [])
  225. def test_ordered(self):
  226. self.assertQuerySetEqual(
  227. Person.objects.order_by("name"),
  228. [self.p1, self.p2],
  229. )
  230. def test_unordered(self):
  231. self.assertQuerySetEqual(
  232. Person.objects.order_by("name"), [self.p2, self.p1], ordered=False
  233. )
  234. def test_queryset(self):
  235. self.assertQuerySetEqual(
  236. Person.objects.order_by("name"),
  237. Person.objects.order_by("name"),
  238. )
  239. def test_flat_values_list(self):
  240. self.assertQuerySetEqual(
  241. Person.objects.order_by("name").values_list("name", flat=True),
  242. ["p1", "p2"],
  243. )
  244. def test_transform(self):
  245. self.assertQuerySetEqual(
  246. Person.objects.order_by("name"),
  247. [self.p1.pk, self.p2.pk],
  248. transform=lambda x: x.pk,
  249. )
  250. def test_repr_transform(self):
  251. self.assertQuerySetEqual(
  252. Person.objects.order_by("name"),
  253. [repr(self.p1), repr(self.p2)],
  254. transform=repr,
  255. )
  256. def test_undefined_order(self):
  257. # Using an unordered queryset with more than one ordered value
  258. # is an error.
  259. msg = (
  260. "Trying to compare non-ordered queryset against more than one "
  261. "ordered value."
  262. )
  263. with self.assertRaisesMessage(ValueError, msg):
  264. self.assertQuerySetEqual(
  265. Person.objects.all(),
  266. [self.p1, self.p2],
  267. )
  268. # No error for one value.
  269. self.assertQuerySetEqual(Person.objects.filter(name="p1"), [self.p1])
  270. def test_repeated_values(self):
  271. """
  272. assertQuerySetEqual checks the number of appearance of each item
  273. when used with option ordered=False.
  274. """
  275. batmobile = Car.objects.create(name="Batmobile")
  276. k2000 = Car.objects.create(name="K 2000")
  277. PossessedCar.objects.bulk_create(
  278. [
  279. PossessedCar(car=batmobile, belongs_to=self.p1),
  280. PossessedCar(car=batmobile, belongs_to=self.p1),
  281. PossessedCar(car=k2000, belongs_to=self.p1),
  282. PossessedCar(car=k2000, belongs_to=self.p1),
  283. PossessedCar(car=k2000, belongs_to=self.p1),
  284. PossessedCar(car=k2000, belongs_to=self.p1),
  285. ]
  286. )
  287. with self.assertRaises(AssertionError):
  288. self.assertQuerySetEqual(
  289. self.p1.cars.all(), [batmobile, k2000], ordered=False
  290. )
  291. self.assertQuerySetEqual(
  292. self.p1.cars.all(), [batmobile] * 2 + [k2000] * 4, ordered=False
  293. )
  294. def test_maxdiff(self):
  295. names = ["Joe Smith %s" % i for i in range(20)]
  296. Person.objects.bulk_create([Person(name=name) for name in names])
  297. names.append("Extra Person")
  298. with self.assertRaises(AssertionError) as ctx:
  299. self.assertQuerySetEqual(
  300. Person.objects.filter(name__startswith="Joe"),
  301. names,
  302. ordered=False,
  303. transform=lambda p: p.name,
  304. )
  305. self.assertIn("Set self.maxDiff to None to see it.", str(ctx.exception))
  306. original = self.maxDiff
  307. self.maxDiff = None
  308. try:
  309. with self.assertRaises(AssertionError) as ctx:
  310. self.assertQuerySetEqual(
  311. Person.objects.filter(name__startswith="Joe"),
  312. names,
  313. ordered=False,
  314. transform=lambda p: p.name,
  315. )
  316. finally:
  317. self.maxDiff = original
  318. exception_msg = str(ctx.exception)
  319. self.assertNotIn("Set self.maxDiff to None to see it.", exception_msg)
  320. for name in names:
  321. self.assertIn(name, exception_msg)
  322. @override_settings(ROOT_URLCONF="test_utils.urls")
  323. class CaptureQueriesContextManagerTests(TestCase):
  324. @classmethod
  325. def setUpTestData(cls):
  326. cls.person_pk = str(Person.objects.create(name="test").pk)
  327. def test_simple(self):
  328. with CaptureQueriesContext(connection) as captured_queries:
  329. Person.objects.get(pk=self.person_pk)
  330. self.assertEqual(len(captured_queries), 1)
  331. self.assertIn(self.person_pk, captured_queries[0]["sql"])
  332. with CaptureQueriesContext(connection) as captured_queries:
  333. pass
  334. self.assertEqual(0, len(captured_queries))
  335. def test_within(self):
  336. with CaptureQueriesContext(connection) as captured_queries:
  337. Person.objects.get(pk=self.person_pk)
  338. self.assertEqual(len(captured_queries), 1)
  339. self.assertIn(self.person_pk, captured_queries[0]["sql"])
  340. def test_nested(self):
  341. with CaptureQueriesContext(connection) as captured_queries:
  342. Person.objects.count()
  343. with CaptureQueriesContext(connection) as nested_captured_queries:
  344. Person.objects.count()
  345. self.assertEqual(1, len(nested_captured_queries))
  346. self.assertEqual(2, len(captured_queries))
  347. def test_failure(self):
  348. with self.assertRaises(TypeError):
  349. with CaptureQueriesContext(connection):
  350. raise TypeError
  351. def test_with_client(self):
  352. with CaptureQueriesContext(connection) as captured_queries:
  353. self.client.get("/test_utils/get_person/%s/" % self.person_pk)
  354. self.assertEqual(len(captured_queries), 1)
  355. self.assertIn(self.person_pk, captured_queries[0]["sql"])
  356. with CaptureQueriesContext(connection) as captured_queries:
  357. self.client.get("/test_utils/get_person/%s/" % self.person_pk)
  358. self.assertEqual(len(captured_queries), 1)
  359. self.assertIn(self.person_pk, captured_queries[0]["sql"])
  360. with CaptureQueriesContext(connection) as captured_queries:
  361. self.client.get("/test_utils/get_person/%s/" % self.person_pk)
  362. self.client.get("/test_utils/get_person/%s/" % self.person_pk)
  363. self.assertEqual(len(captured_queries), 2)
  364. self.assertIn(self.person_pk, captured_queries[0]["sql"])
  365. self.assertIn(self.person_pk, captured_queries[1]["sql"])
  366. @override_settings(ROOT_URLCONF="test_utils.urls")
  367. class AssertNumQueriesContextManagerTests(TestCase):
  368. def test_simple(self):
  369. with self.assertNumQueries(0):
  370. pass
  371. with self.assertNumQueries(1):
  372. Person.objects.count()
  373. with self.assertNumQueries(2):
  374. Person.objects.count()
  375. Person.objects.count()
  376. def test_failure(self):
  377. msg = "1 != 2 : 1 queries executed, 2 expected\nCaptured queries were:\n1."
  378. with self.assertRaisesMessage(AssertionError, msg):
  379. with self.assertNumQueries(2):
  380. Person.objects.count()
  381. with self.assertRaises(TypeError):
  382. with self.assertNumQueries(4000):
  383. raise TypeError
  384. def test_with_client(self):
  385. person = Person.objects.create(name="test")
  386. with self.assertNumQueries(1):
  387. self.client.get("/test_utils/get_person/%s/" % person.pk)
  388. with self.assertNumQueries(1):
  389. self.client.get("/test_utils/get_person/%s/" % person.pk)
  390. with self.assertNumQueries(2):
  391. self.client.get("/test_utils/get_person/%s/" % person.pk)
  392. self.client.get("/test_utils/get_person/%s/" % person.pk)
  393. @override_settings(ROOT_URLCONF="test_utils.urls")
  394. class AssertTemplateUsedContextManagerTests(SimpleTestCase):
  395. def test_usage(self):
  396. with self.assertTemplateUsed("template_used/base.html"):
  397. render_to_string("template_used/base.html")
  398. with self.assertTemplateUsed(template_name="template_used/base.html"):
  399. render_to_string("template_used/base.html")
  400. with self.assertTemplateUsed("template_used/base.html"):
  401. render_to_string("template_used/include.html")
  402. with self.assertTemplateUsed("template_used/base.html"):
  403. render_to_string("template_used/extends.html")
  404. with self.assertTemplateUsed("template_used/base.html"):
  405. render_to_string("template_used/base.html")
  406. render_to_string("template_used/base.html")
  407. def test_nested_usage(self):
  408. with self.assertTemplateUsed("template_used/base.html"):
  409. with self.assertTemplateUsed("template_used/include.html"):
  410. render_to_string("template_used/include.html")
  411. with self.assertTemplateUsed("template_used/extends.html"):
  412. with self.assertTemplateUsed("template_used/base.html"):
  413. render_to_string("template_used/extends.html")
  414. with self.assertTemplateUsed("template_used/base.html"):
  415. with self.assertTemplateUsed("template_used/alternative.html"):
  416. render_to_string("template_used/alternative.html")
  417. render_to_string("template_used/base.html")
  418. with self.assertTemplateUsed("template_used/base.html"):
  419. render_to_string("template_used/extends.html")
  420. with self.assertTemplateNotUsed("template_used/base.html"):
  421. render_to_string("template_used/alternative.html")
  422. render_to_string("template_used/base.html")
  423. def test_not_used(self):
  424. with self.assertTemplateNotUsed("template_used/base.html"):
  425. pass
  426. with self.assertTemplateNotUsed("template_used/alternative.html"):
  427. pass
  428. def test_error_message(self):
  429. msg = "No templates used to render the response"
  430. with self.assertRaisesMessage(AssertionError, msg):
  431. with self.assertTemplateUsed("template_used/base.html"):
  432. pass
  433. with self.assertRaisesMessage(AssertionError, msg):
  434. with self.assertTemplateUsed(template_name="template_used/base.html"):
  435. pass
  436. msg2 = (
  437. "Template 'template_used/base.html' was not a template used to render "
  438. "the response. Actual template(s) used: template_used/alternative.html"
  439. )
  440. with self.assertRaisesMessage(AssertionError, msg2):
  441. with self.assertTemplateUsed("template_used/base.html"):
  442. render_to_string("template_used/alternative.html")
  443. msg = "No templates used to render the response"
  444. with self.assertRaisesMessage(AssertionError, msg):
  445. response = self.client.get("/test_utils/no_template_used/")
  446. self.assertTemplateUsed(response, "template_used/base.html")
  447. with self.assertRaisesMessage(AssertionError, msg):
  448. with self.assertTemplateUsed("template_used/base.html"):
  449. self.client.get("/test_utils/no_template_used/")
  450. with self.assertRaisesMessage(AssertionError, msg):
  451. with self.assertTemplateUsed("template_used/base.html"):
  452. template = Template("template_used/alternative.html", name=None)
  453. template.render(Context())
  454. def test_msg_prefix(self):
  455. msg_prefix = "Prefix"
  456. msg = f"{msg_prefix}: No templates used to render the response"
  457. with self.assertRaisesMessage(AssertionError, msg):
  458. with self.assertTemplateUsed(
  459. "template_used/base.html", msg_prefix=msg_prefix
  460. ):
  461. pass
  462. with self.assertRaisesMessage(AssertionError, msg):
  463. with self.assertTemplateUsed(
  464. template_name="template_used/base.html",
  465. msg_prefix=msg_prefix,
  466. ):
  467. pass
  468. msg = (
  469. f"{msg_prefix}: Template 'template_used/base.html' was not a "
  470. f"template used to render the response. Actual template(s) used: "
  471. f"template_used/alternative.html"
  472. )
  473. with self.assertRaisesMessage(AssertionError, msg):
  474. with self.assertTemplateUsed(
  475. "template_used/base.html", msg_prefix=msg_prefix
  476. ):
  477. render_to_string("template_used/alternative.html")
  478. def test_count(self):
  479. with self.assertTemplateUsed("template_used/base.html", count=2):
  480. render_to_string("template_used/base.html")
  481. render_to_string("template_used/base.html")
  482. msg = (
  483. "Template 'template_used/base.html' was expected to be rendered "
  484. "3 time(s) but was actually rendered 2 time(s)."
  485. )
  486. with self.assertRaisesMessage(AssertionError, msg):
  487. with self.assertTemplateUsed("template_used/base.html", count=3):
  488. render_to_string("template_used/base.html")
  489. render_to_string("template_used/base.html")
  490. def test_failure(self):
  491. msg = "response and/or template_name argument must be provided"
  492. with self.assertRaisesMessage(TypeError, msg):
  493. with self.assertTemplateUsed():
  494. pass
  495. msg = "No templates used to render the response"
  496. with self.assertRaisesMessage(AssertionError, msg):
  497. with self.assertTemplateUsed(""):
  498. pass
  499. with self.assertRaisesMessage(AssertionError, msg):
  500. with self.assertTemplateUsed(""):
  501. render_to_string("template_used/base.html")
  502. with self.assertRaisesMessage(AssertionError, msg):
  503. with self.assertTemplateUsed(template_name=""):
  504. pass
  505. msg = (
  506. "Template 'template_used/base.html' was not a template used to "
  507. "render the response. Actual template(s) used: "
  508. "template_used/alternative.html"
  509. )
  510. with self.assertRaisesMessage(AssertionError, msg):
  511. with self.assertTemplateUsed("template_used/base.html"):
  512. render_to_string("template_used/alternative.html")
  513. def test_assert_used_on_http_response(self):
  514. response = HttpResponse()
  515. msg = "%s() is only usable on responses fetched using the Django test Client."
  516. with self.assertRaisesMessage(ValueError, msg % "assertTemplateUsed"):
  517. self.assertTemplateUsed(response, "template.html")
  518. with self.assertRaisesMessage(ValueError, msg % "assertTemplateNotUsed"):
  519. self.assertTemplateNotUsed(response, "template.html")
  520. class HTMLEqualTests(SimpleTestCase):
  521. def test_html_parser(self):
  522. element = parse_html("<div><p>Hello</p></div>")
  523. self.assertEqual(len(element.children), 1)
  524. self.assertEqual(element.children[0].name, "p")
  525. self.assertEqual(element.children[0].children[0], "Hello")
  526. parse_html("<p>")
  527. parse_html("<p attr>")
  528. dom = parse_html("<p>foo")
  529. self.assertEqual(len(dom.children), 1)
  530. self.assertEqual(dom.name, "p")
  531. self.assertEqual(dom[0], "foo")
  532. def test_parse_html_in_script(self):
  533. parse_html('<script>var a = "<p" + ">";</script>')
  534. parse_html(
  535. """
  536. <script>
  537. var js_sha_link='<p>***</p>';
  538. </script>
  539. """
  540. )
  541. # script content will be parsed to text
  542. dom = parse_html(
  543. """
  544. <script><p>foo</p> '</scr'+'ipt>' <span>bar</span></script>
  545. """
  546. )
  547. self.assertEqual(len(dom.children), 1)
  548. self.assertEqual(dom.children[0], "<p>foo</p> '</scr'+'ipt>' <span>bar</span>")
  549. def test_void_elements(self):
  550. for tag in VOID_ELEMENTS:
  551. with self.subTest(tag):
  552. dom = parse_html("<p>Hello <%s> world</p>" % tag)
  553. self.assertEqual(len(dom.children), 3)
  554. self.assertEqual(dom[0], "Hello")
  555. self.assertEqual(dom[1].name, tag)
  556. self.assertEqual(dom[2], "world")
  557. dom = parse_html("<p>Hello <%s /> world</p>" % tag)
  558. self.assertEqual(len(dom.children), 3)
  559. self.assertEqual(dom[0], "Hello")
  560. self.assertEqual(dom[1].name, tag)
  561. self.assertEqual(dom[2], "world")
  562. def test_simple_equal_html(self):
  563. self.assertHTMLEqual("", "")
  564. self.assertHTMLEqual("<p></p>", "<p></p>")
  565. self.assertHTMLEqual("<p></p>", " <p> </p> ")
  566. self.assertHTMLEqual("<div><p>Hello</p></div>", "<div><p>Hello</p></div>")
  567. self.assertHTMLEqual("<div><p>Hello</p></div>", "<div> <p>Hello</p> </div>")
  568. self.assertHTMLEqual("<div>\n<p>Hello</p></div>", "<div><p>Hello</p></div>\n")
  569. self.assertHTMLEqual(
  570. "<div><p>Hello\nWorld !</p></div>", "<div><p>Hello World\n!</p></div>"
  571. )
  572. self.assertHTMLEqual(
  573. "<div><p>Hello\nWorld !</p></div>", "<div><p>Hello World\n!</p></div>"
  574. )
  575. self.assertHTMLEqual("<p>Hello World !</p>", "<p>Hello World\n\n!</p>")
  576. self.assertHTMLEqual("<p> </p>", "<p></p>")
  577. self.assertHTMLEqual("<p/>", "<p></p>")
  578. self.assertHTMLEqual("<p />", "<p></p>")
  579. self.assertHTMLEqual("<input checked>", '<input checked="checked">')
  580. self.assertHTMLEqual("<p>Hello", "<p> Hello")
  581. self.assertHTMLEqual("<p>Hello</p>World", "<p>Hello</p> World")
  582. def test_ignore_comments(self):
  583. self.assertHTMLEqual(
  584. "<div>Hello<!-- this is a comment --> World!</div>",
  585. "<div>Hello World!</div>",
  586. )
  587. def test_unequal_html(self):
  588. self.assertHTMLNotEqual("<p>Hello</p>", "<p>Hello!</p>")
  589. self.assertHTMLNotEqual("<p>foo&#20;bar</p>", "<p>foo&nbsp;bar</p>")
  590. self.assertHTMLNotEqual("<p>foo bar</p>", "<p>foo &nbsp;bar</p>")
  591. self.assertHTMLNotEqual("<p>foo nbsp</p>", "<p>foo &nbsp;</p>")
  592. self.assertHTMLNotEqual("<p>foo #20</p>", "<p>foo &#20;</p>")
  593. self.assertHTMLNotEqual(
  594. "<p><span>Hello</span><span>World</span></p>",
  595. "<p><span>Hello</span>World</p>",
  596. )
  597. self.assertHTMLNotEqual(
  598. "<p><span>Hello</span>World</p>",
  599. "<p><span>Hello</span><span>World</span></p>",
  600. )
  601. def test_attributes(self):
  602. self.assertHTMLEqual(
  603. '<input type="text" id="id_name" />', '<input id="id_name" type="text" />'
  604. )
  605. self.assertHTMLEqual(
  606. """<input type='text' id="id_name" />""",
  607. '<input id="id_name" type="text" />',
  608. )
  609. self.assertHTMLNotEqual(
  610. '<input type="text" id="id_name" />',
  611. '<input type="password" id="id_name" />',
  612. )
  613. def test_class_attribute(self):
  614. pairs = [
  615. ('<p class="foo bar"></p>', '<p class="bar foo"></p>'),
  616. ('<p class=" foo bar "></p>', '<p class="bar foo"></p>'),
  617. ('<p class=" foo bar "></p>', '<p class="bar foo"></p>'),
  618. ('<p class="foo\tbar"></p>', '<p class="bar foo"></p>'),
  619. ('<p class="\tfoo\tbar\t"></p>', '<p class="bar foo"></p>'),
  620. ('<p class="\t\t\tfoo\t\t\tbar\t\t\t"></p>', '<p class="bar foo"></p>'),
  621. ('<p class="\t \nfoo \t\nbar\n\t "></p>', '<p class="bar foo"></p>'),
  622. ]
  623. for html1, html2 in pairs:
  624. with self.subTest(html1):
  625. self.assertHTMLEqual(html1, html2)
  626. def test_boolean_attribute(self):
  627. html1 = "<input checked>"
  628. html2 = '<input checked="">'
  629. html3 = '<input checked="checked">'
  630. self.assertHTMLEqual(html1, html2)
  631. self.assertHTMLEqual(html1, html3)
  632. self.assertHTMLEqual(html2, html3)
  633. self.assertHTMLNotEqual(html1, '<input checked="invalid">')
  634. self.assertEqual(str(parse_html(html1)), "<input checked>")
  635. self.assertEqual(str(parse_html(html2)), "<input checked>")
  636. self.assertEqual(str(parse_html(html3)), "<input checked>")
  637. def test_non_boolean_attibutes(self):
  638. html1 = "<input value>"
  639. html2 = '<input value="">'
  640. html3 = '<input value="value">'
  641. self.assertHTMLEqual(html1, html2)
  642. self.assertHTMLNotEqual(html1, html3)
  643. self.assertEqual(str(parse_html(html1)), '<input value="">')
  644. self.assertEqual(str(parse_html(html2)), '<input value="">')
  645. def test_normalize_refs(self):
  646. pairs = [
  647. ("&#39;", "&#x27;"),
  648. ("&#39;", "'"),
  649. ("&#x27;", "&#39;"),
  650. ("&#x27;", "'"),
  651. ("'", "&#39;"),
  652. ("'", "&#x27;"),
  653. ("&amp;", "&#38;"),
  654. ("&amp;", "&#x26;"),
  655. ("&amp;", "&"),
  656. ("&#38;", "&amp;"),
  657. ("&#38;", "&#x26;"),
  658. ("&#38;", "&"),
  659. ("&#x26;", "&amp;"),
  660. ("&#x26;", "&#38;"),
  661. ("&#x26;", "&"),
  662. ("&", "&amp;"),
  663. ("&", "&#38;"),
  664. ("&", "&#x26;"),
  665. ]
  666. for pair in pairs:
  667. with self.subTest(repr(pair)):
  668. self.assertHTMLEqual(*pair)
  669. def test_complex_examples(self):
  670. self.assertHTMLEqual(
  671. """<tr><th><label for="id_first_name">First name:</label></th>
  672. <td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>
  673. <tr><th><label for="id_last_name">Last name:</label></th>
  674. <td><input type="text" id="id_last_name" name="last_name" value="Lennon" /></td></tr>
  675. <tr><th><label for="id_birthday">Birthday:</label></th>
  676. <td><input type="text" value="1940-10-9" name="birthday" id="id_birthday" /></td></tr>""", # NOQA
  677. """
  678. <tr><th>
  679. <label for="id_first_name">First name:</label></th><td>
  680. <input type="text" name="first_name" value="John" id="id_first_name" />
  681. </td></tr>
  682. <tr><th>
  683. <label for="id_last_name">Last name:</label></th><td>
  684. <input type="text" name="last_name" value="Lennon" id="id_last_name" />
  685. </td></tr>
  686. <tr><th>
  687. <label for="id_birthday">Birthday:</label></th><td>
  688. <input type="text" name="birthday" value="1940-10-9" id="id_birthday" />
  689. </td></tr>
  690. """,
  691. )
  692. self.assertHTMLEqual(
  693. """<!DOCTYPE html>
  694. <html>
  695. <head>
  696. <link rel="stylesheet">
  697. <title>Document</title>
  698. <meta attribute="value">
  699. </head>
  700. <body>
  701. <p>
  702. This is a valid paragraph
  703. <div> this is a div AFTER the p</div>
  704. </body>
  705. </html>""",
  706. """
  707. <html>
  708. <head>
  709. <link rel="stylesheet">
  710. <title>Document</title>
  711. <meta attribute="value">
  712. </head>
  713. <body>
  714. <p> This is a valid paragraph
  715. <!-- browsers would close the p tag here -->
  716. <div> this is a div AFTER the p</div>
  717. </p> <!-- this is invalid HTML parsing, but it should make no
  718. difference in most cases -->
  719. </body>
  720. </html>""",
  721. )
  722. def test_html_contain(self):
  723. # equal html contains each other
  724. dom1 = parse_html("<p>foo")
  725. dom2 = parse_html("<p>foo</p>")
  726. self.assertIn(dom1, dom2)
  727. self.assertIn(dom2, dom1)
  728. dom2 = parse_html("<div><p>foo</p></div>")
  729. self.assertIn(dom1, dom2)
  730. self.assertNotIn(dom2, dom1)
  731. self.assertNotIn("<p>foo</p>", dom2)
  732. self.assertIn("foo", dom2)
  733. # when a root element is used ...
  734. dom1 = parse_html("<p>foo</p><p>bar</p>")
  735. dom2 = parse_html("<p>foo</p><p>bar</p>")
  736. self.assertIn(dom1, dom2)
  737. dom1 = parse_html("<p>foo</p>")
  738. self.assertIn(dom1, dom2)
  739. dom1 = parse_html("<p>bar</p>")
  740. self.assertIn(dom1, dom2)
  741. dom1 = parse_html("<div><p>foo</p><p>bar</p></div>")
  742. self.assertIn(dom2, dom1)
  743. def test_count(self):
  744. # equal html contains each other one time
  745. dom1 = parse_html("<p>foo")
  746. dom2 = parse_html("<p>foo</p>")
  747. self.assertEqual(dom1.count(dom2), 1)
  748. self.assertEqual(dom2.count(dom1), 1)
  749. dom2 = parse_html("<p>foo</p><p>bar</p>")
  750. self.assertEqual(dom2.count(dom1), 1)
  751. dom2 = parse_html("<p>foo foo</p><p>foo</p>")
  752. self.assertEqual(dom2.count("foo"), 3)
  753. dom2 = parse_html('<p class="bar">foo</p>')
  754. self.assertEqual(dom2.count("bar"), 0)
  755. self.assertEqual(dom2.count("class"), 0)
  756. self.assertEqual(dom2.count("p"), 0)
  757. self.assertEqual(dom2.count("o"), 2)
  758. dom2 = parse_html("<p>foo</p><p>foo</p>")
  759. self.assertEqual(dom2.count(dom1), 2)
  760. dom2 = parse_html('<div><p>foo<input type=""></p><p>foo</p></div>')
  761. self.assertEqual(dom2.count(dom1), 1)
  762. dom2 = parse_html("<div><div><p>foo</p></div></div>")
  763. self.assertEqual(dom2.count(dom1), 1)
  764. dom2 = parse_html("<p>foo<p>foo</p></p>")
  765. self.assertEqual(dom2.count(dom1), 1)
  766. dom2 = parse_html("<p>foo<p>bar</p></p>")
  767. self.assertEqual(dom2.count(dom1), 0)
  768. # HTML with a root element contains the same HTML with no root element.
  769. dom1 = parse_html("<p>foo</p><p>bar</p>")
  770. dom2 = parse_html("<div><p>foo</p><p>bar</p></div>")
  771. self.assertEqual(dom2.count(dom1), 1)
  772. # Target of search is a sequence of child elements and appears more
  773. # than once.
  774. dom2 = parse_html("<div><p>foo</p><p>bar</p><p>foo</p><p>bar</p></div>")
  775. self.assertEqual(dom2.count(dom1), 2)
  776. # Searched HTML has additional children.
  777. dom1 = parse_html("<a/><b/>")
  778. dom2 = parse_html("<a/><b/><c/>")
  779. self.assertEqual(dom2.count(dom1), 1)
  780. # No match found in children.
  781. dom1 = parse_html("<b/><a/>")
  782. self.assertEqual(dom2.count(dom1), 0)
  783. # Target of search found among children and grandchildren.
  784. dom1 = parse_html("<b/><b/>")
  785. dom2 = parse_html("<a><b/><b/></a><b/><b/>")
  786. self.assertEqual(dom2.count(dom1), 2)
  787. def test_root_element_escaped_html(self):
  788. html = "&lt;br&gt;"
  789. parsed = parse_html(html)
  790. self.assertEqual(str(parsed), html)
  791. def test_parsing_errors(self):
  792. with self.assertRaises(AssertionError):
  793. self.assertHTMLEqual("<p>", "")
  794. with self.assertRaises(AssertionError):
  795. self.assertHTMLEqual("", "<p>")
  796. error_msg = (
  797. "First argument is not valid HTML:\n"
  798. "('Unexpected end tag `div` (Line 1, Column 6)', (1, 6))"
  799. )
  800. with self.assertRaisesMessage(AssertionError, error_msg):
  801. self.assertHTMLEqual("< div></ div>", "<div></div>")
  802. with self.assertRaises(HTMLParseError):
  803. parse_html("</p>")
  804. def test_escaped_html_errors(self):
  805. msg = "<p>\n<foo>\n</p> != <p>\n&lt;foo&gt;\n</p>\n"
  806. with self.assertRaisesMessage(AssertionError, msg):
  807. self.assertHTMLEqual("<p><foo></p>", "<p>&lt;foo&gt;</p>")
  808. with self.assertRaisesMessage(AssertionError, msg):
  809. self.assertHTMLEqual("<p><foo></p>", "<p>&#60;foo&#62;</p>")
  810. def test_contains_html(self):
  811. response = HttpResponse(
  812. """<body>
  813. This is a form: <form method="get">
  814. <input type="text" name="Hello" />
  815. </form></body>"""
  816. )
  817. self.assertNotContains(response, "<input name='Hello' type='text'>")
  818. self.assertContains(response, '<form method="get">')
  819. self.assertContains(response, "<input name='Hello' type='text'>", html=True)
  820. self.assertNotContains(response, '<form method="get">', html=True)
  821. invalid_response = HttpResponse("""<body <bad>>""")
  822. with self.assertRaises(AssertionError):
  823. self.assertContains(invalid_response, "<p></p>")
  824. with self.assertRaises(AssertionError):
  825. self.assertContains(response, '<p "whats" that>')
  826. def test_unicode_handling(self):
  827. response = HttpResponse(
  828. '<p class="help">Some help text for the title (with Unicode ŠĐĆŽćžšđ)</p>'
  829. )
  830. self.assertContains(
  831. response,
  832. '<p class="help">Some help text for the title (with Unicode ŠĐĆŽćžšđ)</p>',
  833. html=True,
  834. )
  835. class InHTMLTests(SimpleTestCase):
  836. def test_needle_msg(self):
  837. msg = (
  838. "False is not true : Couldn't find '<b>Hello</b>' in the following "
  839. "response\n'<p>Test</p>'"
  840. )
  841. with self.assertRaisesMessage(AssertionError, msg):
  842. self.assertInHTML("<b>Hello</b>", "<p>Test</p>")
  843. def test_msg_prefix(self):
  844. msg = (
  845. "False is not true : Prefix: Couldn't find '<b>Hello</b>' in the following "
  846. 'response\n\'<input type="text" name="Hello" />\''
  847. )
  848. with self.assertRaisesMessage(AssertionError, msg):
  849. self.assertInHTML(
  850. "<b>Hello</b>",
  851. '<input type="text" name="Hello" />',
  852. msg_prefix="Prefix",
  853. )
  854. def test_count_msg_prefix(self):
  855. msg = (
  856. "2 != 1 : Prefix: Found 2 instances of '<b>Hello</b>' (expected 1) in the "
  857. "following response\n'<b>Hello</b><b>Hello</b>'"
  858. ""
  859. )
  860. with self.assertRaisesMessage(AssertionError, msg):
  861. self.assertInHTML(
  862. "<b>Hello</b>",
  863. "<b>Hello</b><b>Hello</b>",
  864. count=1,
  865. msg_prefix="Prefix",
  866. )
  867. def test_base(self):
  868. haystack = "<p><b>Hello</b> <span>there</span>! Hi <span>there</span>!</p>"
  869. self.assertInHTML("<b>Hello</b>", haystack=haystack)
  870. msg = f"Couldn't find '<p>Howdy</p>' in the following response\n{haystack!r}"
  871. with self.assertRaisesMessage(AssertionError, msg):
  872. self.assertInHTML("<p>Howdy</p>", haystack)
  873. self.assertInHTML("<span>there</span>", haystack=haystack, count=2)
  874. msg = (
  875. "Found 1 instances of '<b>Hello</b>' (expected 2) in the following response"
  876. f"\n{haystack!r}"
  877. )
  878. with self.assertRaisesMessage(AssertionError, msg):
  879. self.assertInHTML("<b>Hello</b>", haystack=haystack, count=2)
  880. def test_long_haystack(self):
  881. haystack = (
  882. "<p>This is a very very very very very very very very long message which "
  883. "exceedes the max limit of truncation.</p>"
  884. )
  885. msg = f"Couldn't find '<b>Hello</b>' in the following response\n{haystack!r}"
  886. with self.assertRaisesMessage(AssertionError, msg):
  887. self.assertInHTML("<b>Hello</b>", haystack)
  888. msg = (
  889. "Found 0 instances of '<b>This</b>' (expected 3) in the following response"
  890. f"\n{haystack!r}"
  891. )
  892. with self.assertRaisesMessage(AssertionError, msg):
  893. self.assertInHTML("<b>This</b>", haystack, 3)
  894. class JSONEqualTests(SimpleTestCase):
  895. def test_simple_equal(self):
  896. json1 = '{"attr1": "foo", "attr2":"baz"}'
  897. json2 = '{"attr1": "foo", "attr2":"baz"}'
  898. self.assertJSONEqual(json1, json2)
  899. def test_simple_equal_unordered(self):
  900. json1 = '{"attr1": "foo", "attr2":"baz"}'
  901. json2 = '{"attr2":"baz", "attr1": "foo"}'
  902. self.assertJSONEqual(json1, json2)
  903. def test_simple_equal_raise(self):
  904. json1 = '{"attr1": "foo", "attr2":"baz"}'
  905. json2 = '{"attr2":"baz"}'
  906. with self.assertRaises(AssertionError):
  907. self.assertJSONEqual(json1, json2)
  908. def test_equal_parsing_errors(self):
  909. invalid_json = '{"attr1": "foo, "attr2":"baz"}'
  910. valid_json = '{"attr1": "foo", "attr2":"baz"}'
  911. with self.assertRaises(AssertionError):
  912. self.assertJSONEqual(invalid_json, valid_json)
  913. with self.assertRaises(AssertionError):
  914. self.assertJSONEqual(valid_json, invalid_json)
  915. def test_simple_not_equal(self):
  916. json1 = '{"attr1": "foo", "attr2":"baz"}'
  917. json2 = '{"attr2":"baz"}'
  918. self.assertJSONNotEqual(json1, json2)
  919. def test_simple_not_equal_raise(self):
  920. json1 = '{"attr1": "foo", "attr2":"baz"}'
  921. json2 = '{"attr1": "foo", "attr2":"baz"}'
  922. with self.assertRaises(AssertionError):
  923. self.assertJSONNotEqual(json1, json2)
  924. def test_not_equal_parsing_errors(self):
  925. invalid_json = '{"attr1": "foo, "attr2":"baz"}'
  926. valid_json = '{"attr1": "foo", "attr2":"baz"}'
  927. with self.assertRaises(AssertionError):
  928. self.assertJSONNotEqual(invalid_json, valid_json)
  929. with self.assertRaises(AssertionError):
  930. self.assertJSONNotEqual(valid_json, invalid_json)
  931. class XMLEqualTests(SimpleTestCase):
  932. def test_simple_equal(self):
  933. xml1 = "<elem attr1='a' attr2='b' />"
  934. xml2 = "<elem attr1='a' attr2='b' />"
  935. self.assertXMLEqual(xml1, xml2)
  936. def test_simple_equal_unordered(self):
  937. xml1 = "<elem attr1='a' attr2='b' />"
  938. xml2 = "<elem attr2='b' attr1='a' />"
  939. self.assertXMLEqual(xml1, xml2)
  940. def test_simple_equal_raise(self):
  941. xml1 = "<elem attr1='a' />"
  942. xml2 = "<elem attr2='b' attr1='a' />"
  943. with self.assertRaises(AssertionError):
  944. self.assertXMLEqual(xml1, xml2)
  945. def test_simple_equal_raises_message(self):
  946. xml1 = "<elem attr1='a' />"
  947. xml2 = "<elem attr2='b' attr1='a' />"
  948. msg = """{xml1} != {xml2}
  949. - <elem attr1='a' />
  950. + <elem attr2='b' attr1='a' />
  951. ? ++++++++++
  952. """.format(
  953. xml1=repr(xml1), xml2=repr(xml2)
  954. )
  955. with self.assertRaisesMessage(AssertionError, msg):
  956. self.assertXMLEqual(xml1, xml2)
  957. def test_simple_not_equal(self):
  958. xml1 = "<elem attr1='a' attr2='c' />"
  959. xml2 = "<elem attr1='a' attr2='b' />"
  960. self.assertXMLNotEqual(xml1, xml2)
  961. def test_simple_not_equal_raise(self):
  962. xml1 = "<elem attr1='a' attr2='b' />"
  963. xml2 = "<elem attr2='b' attr1='a' />"
  964. with self.assertRaises(AssertionError):
  965. self.assertXMLNotEqual(xml1, xml2)
  966. def test_parsing_errors(self):
  967. xml_unvalid = "<elem attr1='a attr2='b' />"
  968. xml2 = "<elem attr2='b' attr1='a' />"
  969. with self.assertRaises(AssertionError):
  970. self.assertXMLNotEqual(xml_unvalid, xml2)
  971. def test_comment_root(self):
  972. xml1 = "<?xml version='1.0'?><!-- comment1 --><elem attr1='a' attr2='b' />"
  973. xml2 = "<?xml version='1.0'?><!-- comment2 --><elem attr2='b' attr1='a' />"
  974. self.assertXMLEqual(xml1, xml2)
  975. def test_simple_equal_with_leading_or_trailing_whitespace(self):
  976. xml1 = "<elem>foo</elem> \t\n"
  977. xml2 = " \t\n<elem>foo</elem>"
  978. self.assertXMLEqual(xml1, xml2)
  979. def test_simple_not_equal_with_whitespace_in_the_middle(self):
  980. xml1 = "<elem>foo</elem><elem>bar</elem>"
  981. xml2 = "<elem>foo</elem> <elem>bar</elem>"
  982. self.assertXMLNotEqual(xml1, xml2)
  983. def test_doctype_root(self):
  984. xml1 = '<?xml version="1.0"?><!DOCTYPE root SYSTEM "example1.dtd"><root />'
  985. xml2 = '<?xml version="1.0"?><!DOCTYPE root SYSTEM "example2.dtd"><root />'
  986. self.assertXMLEqual(xml1, xml2)
  987. def test_processing_instruction(self):
  988. xml1 = (
  989. '<?xml version="1.0"?>'
  990. '<?xml-model href="http://www.example1.com"?><root />'
  991. )
  992. xml2 = (
  993. '<?xml version="1.0"?>'
  994. '<?xml-model href="http://www.example2.com"?><root />'
  995. )
  996. self.assertXMLEqual(xml1, xml2)
  997. self.assertXMLEqual(
  998. '<?xml-stylesheet href="style1.xslt" type="text/xsl"?><root />',
  999. '<?xml-stylesheet href="style2.xslt" type="text/xsl"?><root />',
  1000. )
  1001. class SkippingExtraTests(TestCase):
  1002. fixtures = ["should_not_be_loaded.json"]
  1003. # HACK: This depends on internals of our TestCase subclasses
  1004. def __call__(self, result=None):
  1005. # Detect fixture loading by counting SQL queries, should be zero
  1006. with self.assertNumQueries(0):
  1007. super().__call__(result)
  1008. @unittest.skip("Fixture loading should not be performed for skipped tests.")
  1009. def test_fixtures_are_skipped(self):
  1010. pass
  1011. class AssertRaisesMsgTest(SimpleTestCase):
  1012. def test_assert_raises_message(self):
  1013. msg = "'Expected message' not found in 'Unexpected message'"
  1014. # context manager form of assertRaisesMessage()
  1015. with self.assertRaisesMessage(AssertionError, msg):
  1016. with self.assertRaisesMessage(ValueError, "Expected message"):
  1017. raise ValueError("Unexpected message")
  1018. # callable form
  1019. def func():
  1020. raise ValueError("Unexpected message")
  1021. with self.assertRaisesMessage(AssertionError, msg):
  1022. self.assertRaisesMessage(ValueError, "Expected message", func)
  1023. def test_special_re_chars(self):
  1024. """assertRaisesMessage shouldn't interpret RE special chars."""
  1025. def func1():
  1026. raise ValueError("[.*x+]y?")
  1027. with self.assertRaisesMessage(ValueError, "[.*x+]y?"):
  1028. func1()
  1029. class AssertWarnsMessageTests(SimpleTestCase):
  1030. def test_context_manager(self):
  1031. with self.assertWarnsMessage(UserWarning, "Expected message"):
  1032. warnings.warn("Expected message", UserWarning)
  1033. def test_context_manager_failure(self):
  1034. msg = "Expected message' not found in 'Unexpected message'"
  1035. with self.assertRaisesMessage(AssertionError, msg):
  1036. with self.assertWarnsMessage(UserWarning, "Expected message"):
  1037. warnings.warn("Unexpected message", UserWarning)
  1038. def test_callable(self):
  1039. def func():
  1040. warnings.warn("Expected message", UserWarning)
  1041. self.assertWarnsMessage(UserWarning, "Expected message", func)
  1042. def test_special_re_chars(self):
  1043. def func1():
  1044. warnings.warn("[.*x+]y?", UserWarning)
  1045. with self.assertWarnsMessage(UserWarning, "[.*x+]y?"):
  1046. func1()
  1047. class AssertFieldOutputTests(SimpleTestCase):
  1048. def test_assert_field_output(self):
  1049. error_invalid = ["Enter a valid email address."]
  1050. self.assertFieldOutput(
  1051. EmailField, {"a@a.com": "a@a.com"}, {"aaa": error_invalid}
  1052. )
  1053. with self.assertRaises(AssertionError):
  1054. self.assertFieldOutput(
  1055. EmailField,
  1056. {"a@a.com": "a@a.com"},
  1057. {"aaa": error_invalid + ["Another error"]},
  1058. )
  1059. with self.assertRaises(AssertionError):
  1060. self.assertFieldOutput(
  1061. EmailField, {"a@a.com": "Wrong output"}, {"aaa": error_invalid}
  1062. )
  1063. with self.assertRaises(AssertionError):
  1064. self.assertFieldOutput(
  1065. EmailField,
  1066. {"a@a.com": "a@a.com"},
  1067. {"aaa": ["Come on, gimme some well formatted data, dude."]},
  1068. )
  1069. def test_custom_required_message(self):
  1070. class MyCustomField(IntegerField):
  1071. default_error_messages = {
  1072. "required": "This is really required.",
  1073. }
  1074. self.assertFieldOutput(MyCustomField, {}, {}, empty_value=None)
  1075. @override_settings(ROOT_URLCONF="test_utils.urls")
  1076. class AssertURLEqualTests(SimpleTestCase):
  1077. def test_equal(self):
  1078. valid_tests = (
  1079. ("http://example.com/?", "http://example.com/"),
  1080. ("http://example.com/?x=1&", "http://example.com/?x=1"),
  1081. ("http://example.com/?x=1&y=2", "http://example.com/?y=2&x=1"),
  1082. ("http://example.com/?x=1&y=2", "http://example.com/?y=2&x=1"),
  1083. (
  1084. "http://example.com/?x=1&y=2&a=1&a=2",
  1085. "http://example.com/?a=1&a=2&y=2&x=1",
  1086. ),
  1087. ("/path/to/?x=1&y=2&z=3", "/path/to/?z=3&y=2&x=1"),
  1088. ("?x=1&y=2&z=3", "?z=3&y=2&x=1"),
  1089. ("/test_utils/no_template_used/", reverse_lazy("no_template_used")),
  1090. )
  1091. for url1, url2 in valid_tests:
  1092. with self.subTest(url=url1):
  1093. self.assertURLEqual(url1, url2)
  1094. def test_not_equal(self):
  1095. invalid_tests = (
  1096. # Protocol must be the same.
  1097. ("http://example.com/", "https://example.com/"),
  1098. ("http://example.com/?x=1&x=2", "https://example.com/?x=2&x=1"),
  1099. ("http://example.com/?x=1&y=bar&x=2", "https://example.com/?y=bar&x=2&x=1"),
  1100. # Parameters of the same name must be in the same order.
  1101. ("/path/to?a=1&a=2", "/path/to/?a=2&a=1"),
  1102. )
  1103. for url1, url2 in invalid_tests:
  1104. with self.subTest(url=url1), self.assertRaises(AssertionError):
  1105. self.assertURLEqual(url1, url2)
  1106. def test_message(self):
  1107. msg = (
  1108. "Expected 'http://example.com/?x=1&x=2' to equal "
  1109. "'https://example.com/?x=2&x=1'"
  1110. )
  1111. with self.assertRaisesMessage(AssertionError, msg):
  1112. self.assertURLEqual(
  1113. "http://example.com/?x=1&x=2", "https://example.com/?x=2&x=1"
  1114. )
  1115. def test_msg_prefix(self):
  1116. msg = (
  1117. "Prefix: Expected 'http://example.com/?x=1&x=2' to equal "
  1118. "'https://example.com/?x=2&x=1'"
  1119. )
  1120. with self.assertRaisesMessage(AssertionError, msg):
  1121. self.assertURLEqual(
  1122. "http://example.com/?x=1&x=2",
  1123. "https://example.com/?x=2&x=1",
  1124. msg_prefix="Prefix",
  1125. )
  1126. class TestForm(Form):
  1127. field = CharField()
  1128. def clean_field(self):
  1129. value = self.cleaned_data.get("field", "")
  1130. if value == "invalid":
  1131. raise ValidationError("invalid value")
  1132. return value
  1133. def clean(self):
  1134. if self.cleaned_data.get("field") == "invalid_non_field":
  1135. raise ValidationError("non-field error")
  1136. return self.cleaned_data
  1137. @classmethod
  1138. def _get_cleaned_form(cls, field_value):
  1139. form = cls({"field": field_value})
  1140. form.full_clean()
  1141. return form
  1142. @classmethod
  1143. def valid(cls):
  1144. return cls._get_cleaned_form("valid")
  1145. @classmethod
  1146. def invalid(cls, nonfield=False):
  1147. return cls._get_cleaned_form("invalid_non_field" if nonfield else "invalid")
  1148. class TestFormset(formset_factory(TestForm)):
  1149. @classmethod
  1150. def _get_cleaned_formset(cls, field_value):
  1151. formset = cls(
  1152. {
  1153. "form-TOTAL_FORMS": "1",
  1154. "form-INITIAL_FORMS": "0",
  1155. "form-0-field": field_value,
  1156. }
  1157. )
  1158. formset.full_clean()
  1159. return formset
  1160. @classmethod
  1161. def valid(cls):
  1162. return cls._get_cleaned_formset("valid")
  1163. @classmethod
  1164. def invalid(cls, nonfield=False, nonform=False):
  1165. if nonform:
  1166. formset = cls({}, error_messages={"missing_management_form": "error"})
  1167. formset.full_clean()
  1168. return formset
  1169. return cls._get_cleaned_formset("invalid_non_field" if nonfield else "invalid")
  1170. class AssertFormErrorTests(SimpleTestCase):
  1171. def test_single_error(self):
  1172. self.assertFormError(TestForm.invalid(), "field", "invalid value")
  1173. def test_error_list(self):
  1174. self.assertFormError(TestForm.invalid(), "field", ["invalid value"])
  1175. def test_empty_errors_valid_form(self):
  1176. self.assertFormError(TestForm.valid(), "field", [])
  1177. def test_empty_errors_valid_form_non_field_errors(self):
  1178. self.assertFormError(TestForm.valid(), None, [])
  1179. def test_field_not_in_form(self):
  1180. msg = (
  1181. "The form <TestForm bound=True, valid=False, fields=(field)> does not "
  1182. "contain the field 'other_field'."
  1183. )
  1184. with self.assertRaisesMessage(AssertionError, msg):
  1185. self.assertFormError(TestForm.invalid(), "other_field", "invalid value")
  1186. msg_prefix = "Custom prefix"
  1187. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1188. self.assertFormError(
  1189. TestForm.invalid(),
  1190. "other_field",
  1191. "invalid value",
  1192. msg_prefix=msg_prefix,
  1193. )
  1194. def test_field_with_no_errors(self):
  1195. msg = (
  1196. "The errors of field 'field' on form <TestForm bound=True, valid=True, "
  1197. "fields=(field)> don't match."
  1198. )
  1199. with self.assertRaisesMessage(AssertionError, msg) as ctx:
  1200. self.assertFormError(TestForm.valid(), "field", "invalid value")
  1201. self.assertIn("[] != ['invalid value']", str(ctx.exception))
  1202. msg_prefix = "Custom prefix"
  1203. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1204. self.assertFormError(
  1205. TestForm.valid(), "field", "invalid value", msg_prefix=msg_prefix
  1206. )
  1207. def test_field_with_different_error(self):
  1208. msg = (
  1209. "The errors of field 'field' on form <TestForm bound=True, valid=False, "
  1210. "fields=(field)> don't match."
  1211. )
  1212. with self.assertRaisesMessage(AssertionError, msg) as ctx:
  1213. self.assertFormError(TestForm.invalid(), "field", "other error")
  1214. self.assertIn("['invalid value'] != ['other error']", str(ctx.exception))
  1215. msg_prefix = "Custom prefix"
  1216. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1217. self.assertFormError(
  1218. TestForm.invalid(), "field", "other error", msg_prefix=msg_prefix
  1219. )
  1220. def test_unbound_form(self):
  1221. msg = (
  1222. "The form <TestForm bound=False, valid=Unknown, fields=(field)> is not "
  1223. "bound, it will never have any errors."
  1224. )
  1225. with self.assertRaisesMessage(AssertionError, msg):
  1226. self.assertFormError(TestForm(), "field", [])
  1227. msg_prefix = "Custom prefix"
  1228. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1229. self.assertFormError(TestForm(), "field", [], msg_prefix=msg_prefix)
  1230. def test_empty_errors_invalid_form(self):
  1231. msg = (
  1232. "The errors of field 'field' on form <TestForm bound=True, valid=False, "
  1233. "fields=(field)> don't match."
  1234. )
  1235. with self.assertRaisesMessage(AssertionError, msg) as ctx:
  1236. self.assertFormError(TestForm.invalid(), "field", [])
  1237. self.assertIn("['invalid value'] != []", str(ctx.exception))
  1238. def test_non_field_errors(self):
  1239. self.assertFormError(TestForm.invalid(nonfield=True), None, "non-field error")
  1240. def test_different_non_field_errors(self):
  1241. msg = (
  1242. "The non-field errors of form <TestForm bound=True, valid=False, "
  1243. "fields=(field)> don't match."
  1244. )
  1245. with self.assertRaisesMessage(AssertionError, msg) as ctx:
  1246. self.assertFormError(
  1247. TestForm.invalid(nonfield=True), None, "other non-field error"
  1248. )
  1249. self.assertIn(
  1250. "['non-field error'] != ['other non-field error']", str(ctx.exception)
  1251. )
  1252. msg_prefix = "Custom prefix"
  1253. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1254. self.assertFormError(
  1255. TestForm.invalid(nonfield=True),
  1256. None,
  1257. "other non-field error",
  1258. msg_prefix=msg_prefix,
  1259. )
  1260. class AssertFormSetErrorTests(SimpleTestCase):
  1261. def test_single_error(self):
  1262. self.assertFormSetError(TestFormset.invalid(), 0, "field", "invalid value")
  1263. def test_error_list(self):
  1264. self.assertFormSetError(TestFormset.invalid(), 0, "field", ["invalid value"])
  1265. def test_empty_errors_valid_formset(self):
  1266. self.assertFormSetError(TestFormset.valid(), 0, "field", [])
  1267. def test_multiple_forms(self):
  1268. formset = TestFormset(
  1269. {
  1270. "form-TOTAL_FORMS": "2",
  1271. "form-INITIAL_FORMS": "0",
  1272. "form-0-field": "valid",
  1273. "form-1-field": "invalid",
  1274. }
  1275. )
  1276. formset.full_clean()
  1277. self.assertFormSetError(formset, 0, "field", [])
  1278. self.assertFormSetError(formset, 1, "field", ["invalid value"])
  1279. def test_field_not_in_form(self):
  1280. msg = (
  1281. "The form 0 of formset <TestFormset: bound=True valid=False total_forms=1> "
  1282. "does not contain the field 'other_field'."
  1283. )
  1284. with self.assertRaisesMessage(AssertionError, msg):
  1285. self.assertFormSetError(
  1286. TestFormset.invalid(), 0, "other_field", "invalid value"
  1287. )
  1288. msg_prefix = "Custom prefix"
  1289. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1290. self.assertFormSetError(
  1291. TestFormset.invalid(),
  1292. 0,
  1293. "other_field",
  1294. "invalid value",
  1295. msg_prefix=msg_prefix,
  1296. )
  1297. def test_field_with_no_errors(self):
  1298. msg = (
  1299. "The errors of field 'field' on form 0 of formset <TestFormset: bound=True "
  1300. "valid=True total_forms=1> don't match."
  1301. )
  1302. with self.assertRaisesMessage(AssertionError, msg) as ctx:
  1303. self.assertFormSetError(TestFormset.valid(), 0, "field", "invalid value")
  1304. self.assertIn("[] != ['invalid value']", str(ctx.exception))
  1305. msg_prefix = "Custom prefix"
  1306. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1307. self.assertFormSetError(
  1308. TestFormset.valid(), 0, "field", "invalid value", msg_prefix=msg_prefix
  1309. )
  1310. def test_field_with_different_error(self):
  1311. msg = (
  1312. "The errors of field 'field' on form 0 of formset <TestFormset: bound=True "
  1313. "valid=False total_forms=1> don't match."
  1314. )
  1315. with self.assertRaisesMessage(AssertionError, msg) as ctx:
  1316. self.assertFormSetError(TestFormset.invalid(), 0, "field", "other error")
  1317. self.assertIn("['invalid value'] != ['other error']", str(ctx.exception))
  1318. msg_prefix = "Custom prefix"
  1319. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1320. self.assertFormSetError(
  1321. TestFormset.invalid(), 0, "field", "other error", msg_prefix=msg_prefix
  1322. )
  1323. def test_unbound_formset(self):
  1324. msg = (
  1325. "The formset <TestFormset: bound=False valid=Unknown total_forms=1> is not "
  1326. "bound, it will never have any errors."
  1327. )
  1328. with self.assertRaisesMessage(AssertionError, msg):
  1329. self.assertFormSetError(TestFormset(), 0, "field", [])
  1330. def test_empty_errors_invalid_formset(self):
  1331. msg = (
  1332. "The errors of field 'field' on form 0 of formset <TestFormset: bound=True "
  1333. "valid=False total_forms=1> don't match."
  1334. )
  1335. with self.assertRaisesMessage(AssertionError, msg) as ctx:
  1336. self.assertFormSetError(TestFormset.invalid(), 0, "field", [])
  1337. self.assertIn("['invalid value'] != []", str(ctx.exception))
  1338. def test_non_field_errors(self):
  1339. self.assertFormSetError(
  1340. TestFormset.invalid(nonfield=True), 0, None, "non-field error"
  1341. )
  1342. def test_different_non_field_errors(self):
  1343. msg = (
  1344. "The non-field errors of form 0 of formset <TestFormset: bound=True "
  1345. "valid=False total_forms=1> don't match."
  1346. )
  1347. with self.assertRaisesMessage(AssertionError, msg) as ctx:
  1348. self.assertFormSetError(
  1349. TestFormset.invalid(nonfield=True), 0, None, "other non-field error"
  1350. )
  1351. self.assertIn(
  1352. "['non-field error'] != ['other non-field error']", str(ctx.exception)
  1353. )
  1354. msg_prefix = "Custom prefix"
  1355. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1356. self.assertFormSetError(
  1357. TestFormset.invalid(nonfield=True),
  1358. 0,
  1359. None,
  1360. "other non-field error",
  1361. msg_prefix=msg_prefix,
  1362. )
  1363. def test_no_non_field_errors(self):
  1364. msg = (
  1365. "The non-field errors of form 0 of formset <TestFormset: bound=True "
  1366. "valid=False total_forms=1> don't match."
  1367. )
  1368. with self.assertRaisesMessage(AssertionError, msg) as ctx:
  1369. self.assertFormSetError(TestFormset.invalid(), 0, None, "non-field error")
  1370. self.assertIn("[] != ['non-field error']", str(ctx.exception))
  1371. msg_prefix = "Custom prefix"
  1372. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1373. self.assertFormSetError(
  1374. TestFormset.invalid(), 0, None, "non-field error", msg_prefix=msg_prefix
  1375. )
  1376. def test_non_form_errors(self):
  1377. self.assertFormSetError(TestFormset.invalid(nonform=True), None, None, "error")
  1378. def test_different_non_form_errors(self):
  1379. msg = (
  1380. "The non-form errors of formset <TestFormset: bound=True valid=False "
  1381. "total_forms=0> don't match."
  1382. )
  1383. with self.assertRaisesMessage(AssertionError, msg) as ctx:
  1384. self.assertFormSetError(
  1385. TestFormset.invalid(nonform=True), None, None, "other error"
  1386. )
  1387. self.assertIn("['error'] != ['other error']", str(ctx.exception))
  1388. msg_prefix = "Custom prefix"
  1389. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1390. self.assertFormSetError(
  1391. TestFormset.invalid(nonform=True),
  1392. None,
  1393. None,
  1394. "other error",
  1395. msg_prefix=msg_prefix,
  1396. )
  1397. def test_no_non_form_errors(self):
  1398. msg = (
  1399. "The non-form errors of formset <TestFormset: bound=True valid=False "
  1400. "total_forms=1> don't match."
  1401. )
  1402. with self.assertRaisesMessage(AssertionError, msg) as ctx:
  1403. self.assertFormSetError(TestFormset.invalid(), None, None, "error")
  1404. self.assertIn("[] != ['error']", str(ctx.exception))
  1405. msg_prefix = "Custom prefix"
  1406. with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
  1407. self.assertFormSetError(
  1408. TestFormset.invalid(),
  1409. None,
  1410. None,
  1411. "error",
  1412. msg_prefix=msg_prefix,
  1413. )
  1414. def test_non_form_errors_with_field(self):
  1415. msg = "You must use field=None with form_index=None."
  1416. with self.assertRaisesMessage(ValueError, msg):
  1417. self.assertFormSetError(
  1418. TestFormset.invalid(nonform=True), None, "field", "error"
  1419. )
  1420. def test_form_index_too_big(self):
  1421. msg = (
  1422. "The formset <TestFormset: bound=True valid=False total_forms=1> only has "
  1423. "1 form."
  1424. )
  1425. with self.assertRaisesMessage(AssertionError, msg):
  1426. self.assertFormSetError(TestFormset.invalid(), 2, "field", "error")
  1427. def test_form_index_too_big_plural(self):
  1428. formset = TestFormset(
  1429. {
  1430. "form-TOTAL_FORMS": "2",
  1431. "form-INITIAL_FORMS": "0",
  1432. "form-0-field": "valid",
  1433. "form-1-field": "valid",
  1434. }
  1435. )
  1436. formset.full_clean()
  1437. msg = (
  1438. "The formset <TestFormset: bound=True valid=True total_forms=2> only has 2 "
  1439. "forms."
  1440. )
  1441. with self.assertRaisesMessage(AssertionError, msg):
  1442. self.assertFormSetError(formset, 2, "field", "error")
  1443. class FirstUrls:
  1444. urlpatterns = [path("first/", empty_response, name="first")]
  1445. class SecondUrls:
  1446. urlpatterns = [path("second/", empty_response, name="second")]
  1447. class SetupTestEnvironmentTests(SimpleTestCase):
  1448. def test_setup_test_environment_calling_more_than_once(self):
  1449. with self.assertRaisesMessage(
  1450. RuntimeError, "setup_test_environment() was already called"
  1451. ):
  1452. setup_test_environment()
  1453. def test_allowed_hosts(self):
  1454. for type_ in (list, tuple):
  1455. with self.subTest(type_=type_):
  1456. allowed_hosts = type_("*")
  1457. with mock.patch("django.test.utils._TestState") as x:
  1458. del x.saved_data
  1459. with self.settings(ALLOWED_HOSTS=allowed_hosts):
  1460. setup_test_environment()
  1461. self.assertEqual(settings.ALLOWED_HOSTS, ["*", "testserver"])
  1462. class OverrideSettingsTests(SimpleTestCase):
  1463. # #21518 -- If neither override_settings nor a setting_changed receiver
  1464. # clears the URL cache between tests, then one of test_first or
  1465. # test_second will fail.
  1466. @override_settings(ROOT_URLCONF=FirstUrls)
  1467. def test_urlconf_first(self):
  1468. reverse("first")
  1469. @override_settings(ROOT_URLCONF=SecondUrls)
  1470. def test_urlconf_second(self):
  1471. reverse("second")
  1472. def test_urlconf_cache(self):
  1473. with self.assertRaises(NoReverseMatch):
  1474. reverse("first")
  1475. with self.assertRaises(NoReverseMatch):
  1476. reverse("second")
  1477. with override_settings(ROOT_URLCONF=FirstUrls):
  1478. self.client.get(reverse("first"))
  1479. with self.assertRaises(NoReverseMatch):
  1480. reverse("second")
  1481. with override_settings(ROOT_URLCONF=SecondUrls):
  1482. with self.assertRaises(NoReverseMatch):
  1483. reverse("first")
  1484. self.client.get(reverse("second"))
  1485. self.client.get(reverse("first"))
  1486. with self.assertRaises(NoReverseMatch):
  1487. reverse("second")
  1488. with self.assertRaises(NoReverseMatch):
  1489. reverse("first")
  1490. with self.assertRaises(NoReverseMatch):
  1491. reverse("second")
  1492. def test_override_media_root(self):
  1493. """
  1494. Overriding the MEDIA_ROOT setting should be reflected in the
  1495. base_location attribute of django.core.files.storage.default_storage.
  1496. """
  1497. self.assertEqual(default_storage.base_location, "")
  1498. with self.settings(MEDIA_ROOT="test_value"):
  1499. self.assertEqual(default_storage.base_location, "test_value")
  1500. def test_override_media_url(self):
  1501. """
  1502. Overriding the MEDIA_URL setting should be reflected in the
  1503. base_url attribute of django.core.files.storage.default_storage.
  1504. """
  1505. self.assertEqual(default_storage.base_location, "")
  1506. with self.settings(MEDIA_URL="/test_value/"):
  1507. self.assertEqual(default_storage.base_url, "/test_value/")
  1508. def test_override_file_upload_permissions(self):
  1509. """
  1510. Overriding the FILE_UPLOAD_PERMISSIONS setting should be reflected in
  1511. the file_permissions_mode attribute of
  1512. django.core.files.storage.default_storage.
  1513. """
  1514. self.assertEqual(default_storage.file_permissions_mode, 0o644)
  1515. with self.settings(FILE_UPLOAD_PERMISSIONS=0o777):
  1516. self.assertEqual(default_storage.file_permissions_mode, 0o777)
  1517. def test_override_file_upload_directory_permissions(self):
  1518. """
  1519. Overriding the FILE_UPLOAD_DIRECTORY_PERMISSIONS setting should be
  1520. reflected in the directory_permissions_mode attribute of
  1521. django.core.files.storage.default_storage.
  1522. """
  1523. self.assertIsNone(default_storage.directory_permissions_mode)
  1524. with self.settings(FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o777):
  1525. self.assertEqual(default_storage.directory_permissions_mode, 0o777)
  1526. def test_override_database_routers(self):
  1527. """
  1528. Overriding DATABASE_ROUTERS should update the base router.
  1529. """
  1530. test_routers = [object()]
  1531. with self.settings(DATABASE_ROUTERS=test_routers):
  1532. self.assertEqual(router.routers, test_routers)
  1533. def test_override_static_url(self):
  1534. """
  1535. Overriding the STATIC_URL setting should be reflected in the
  1536. base_url attribute of
  1537. django.contrib.staticfiles.storage.staticfiles_storage.
  1538. """
  1539. with self.settings(STATIC_URL="/test/"):
  1540. self.assertEqual(staticfiles_storage.base_url, "/test/")
  1541. def test_override_static_root(self):
  1542. """
  1543. Overriding the STATIC_ROOT setting should be reflected in the
  1544. location attribute of
  1545. django.contrib.staticfiles.storage.staticfiles_storage.
  1546. """
  1547. with self.settings(STATIC_ROOT="/tmp/test"):
  1548. self.assertEqual(staticfiles_storage.location, os.path.abspath("/tmp/test"))
  1549. def test_override_staticfiles_storage(self):
  1550. """
  1551. Overriding the STORAGES setting should be reflected in
  1552. the value of django.contrib.staticfiles.storage.staticfiles_storage.
  1553. """
  1554. new_class = "ManifestStaticFilesStorage"
  1555. new_storage = "django.contrib.staticfiles.storage." + new_class
  1556. with self.settings(
  1557. STORAGES={STATICFILES_STORAGE_ALIAS: {"BACKEND": new_storage}}
  1558. ):
  1559. self.assertEqual(staticfiles_storage.__class__.__name__, new_class)
  1560. def test_override_staticfiles_finders(self):
  1561. """
  1562. Overriding the STATICFILES_FINDERS setting should be reflected in
  1563. the return value of django.contrib.staticfiles.finders.get_finders.
  1564. """
  1565. current = get_finders()
  1566. self.assertGreater(len(list(current)), 1)
  1567. finders = ["django.contrib.staticfiles.finders.FileSystemFinder"]
  1568. with self.settings(STATICFILES_FINDERS=finders):
  1569. self.assertEqual(len(list(get_finders())), len(finders))
  1570. def test_override_staticfiles_dirs(self):
  1571. """
  1572. Overriding the STATICFILES_DIRS setting should be reflected in
  1573. the locations attribute of the
  1574. django.contrib.staticfiles.finders.FileSystemFinder instance.
  1575. """
  1576. finder = get_finder("django.contrib.staticfiles.finders.FileSystemFinder")
  1577. test_path = "/tmp/test"
  1578. expected_location = ("", test_path)
  1579. self.assertNotIn(expected_location, finder.locations)
  1580. with self.settings(STATICFILES_DIRS=[test_path]):
  1581. finder = get_finder("django.contrib.staticfiles.finders.FileSystemFinder")
  1582. self.assertIn(expected_location, finder.locations)
  1583. @skipUnlessDBFeature("supports_transactions")
  1584. class TestBadSetUpTestData(TestCase):
  1585. """
  1586. An exception in setUpTestData() shouldn't leak a transaction which would
  1587. cascade across the rest of the test suite.
  1588. """
  1589. class MyException(Exception):
  1590. pass
  1591. @classmethod
  1592. def setUpClass(cls):
  1593. try:
  1594. super().setUpClass()
  1595. except cls.MyException:
  1596. cls._in_atomic_block = connection.in_atomic_block
  1597. @classmethod
  1598. def tearDownClass(Cls):
  1599. # override to avoid a second cls._rollback_atomics() which would fail.
  1600. # Normal setUpClass() methods won't have exception handling so this
  1601. # method wouldn't typically be run.
  1602. pass
  1603. @classmethod
  1604. def setUpTestData(cls):
  1605. # Simulate a broken setUpTestData() method.
  1606. raise cls.MyException()
  1607. def test_failure_in_setUpTestData_should_rollback_transaction(self):
  1608. # setUpTestData() should call _rollback_atomics() so that the
  1609. # transaction doesn't leak.
  1610. self.assertFalse(self._in_atomic_block)
  1611. @skipUnlessDBFeature("supports_transactions")
  1612. class CaptureOnCommitCallbacksTests(TestCase):
  1613. databases = {"default", "other"}
  1614. callback_called = False
  1615. def enqueue_callback(self, using="default"):
  1616. def hook():
  1617. self.callback_called = True
  1618. transaction.on_commit(hook, using=using)
  1619. def test_no_arguments(self):
  1620. with self.captureOnCommitCallbacks() as callbacks:
  1621. self.enqueue_callback()
  1622. self.assertEqual(len(callbacks), 1)
  1623. self.assertIs(self.callback_called, False)
  1624. callbacks[0]()
  1625. self.assertIs(self.callback_called, True)
  1626. def test_using(self):
  1627. with self.captureOnCommitCallbacks(using="other") as callbacks:
  1628. self.enqueue_callback(using="other")
  1629. self.assertEqual(len(callbacks), 1)
  1630. self.assertIs(self.callback_called, False)
  1631. callbacks[0]()
  1632. self.assertIs(self.callback_called, True)
  1633. def test_different_using(self):
  1634. with self.captureOnCommitCallbacks(using="default") as callbacks:
  1635. self.enqueue_callback(using="other")
  1636. self.assertEqual(callbacks, [])
  1637. def test_execute(self):
  1638. with self.captureOnCommitCallbacks(execute=True) as callbacks:
  1639. self.enqueue_callback()
  1640. self.assertEqual(len(callbacks), 1)
  1641. self.assertIs(self.callback_called, True)
  1642. def test_pre_callback(self):
  1643. def pre_hook():
  1644. pass
  1645. transaction.on_commit(pre_hook, using="default")
  1646. with self.captureOnCommitCallbacks() as callbacks:
  1647. self.enqueue_callback()
  1648. self.assertEqual(len(callbacks), 1)
  1649. self.assertNotEqual(callbacks[0], pre_hook)
  1650. def test_with_rolled_back_savepoint(self):
  1651. with self.captureOnCommitCallbacks() as callbacks:
  1652. try:
  1653. with transaction.atomic():
  1654. self.enqueue_callback()
  1655. raise IntegrityError
  1656. except IntegrityError:
  1657. # Inner transaction.atomic() has been rolled back.
  1658. pass
  1659. self.assertEqual(callbacks, [])
  1660. def test_execute_recursive(self):
  1661. with self.captureOnCommitCallbacks(execute=True) as callbacks:
  1662. transaction.on_commit(self.enqueue_callback)
  1663. self.assertEqual(len(callbacks), 2)
  1664. self.assertIs(self.callback_called, True)
  1665. def test_execute_tree(self):
  1666. """
  1667. A visualisation of the callback tree tested. Each node is expected to
  1668. be visited only once:
  1669. └─branch_1
  1670. ├─branch_2
  1671. │ ├─leaf_1
  1672. │ └─leaf_2
  1673. └─leaf_3
  1674. """
  1675. branch_1_call_counter = 0
  1676. branch_2_call_counter = 0
  1677. leaf_1_call_counter = 0
  1678. leaf_2_call_counter = 0
  1679. leaf_3_call_counter = 0
  1680. def leaf_1():
  1681. nonlocal leaf_1_call_counter
  1682. leaf_1_call_counter += 1
  1683. def leaf_2():
  1684. nonlocal leaf_2_call_counter
  1685. leaf_2_call_counter += 1
  1686. def leaf_3():
  1687. nonlocal leaf_3_call_counter
  1688. leaf_3_call_counter += 1
  1689. def branch_1():
  1690. nonlocal branch_1_call_counter
  1691. branch_1_call_counter += 1
  1692. transaction.on_commit(branch_2)
  1693. transaction.on_commit(leaf_3)
  1694. def branch_2():
  1695. nonlocal branch_2_call_counter
  1696. branch_2_call_counter += 1
  1697. transaction.on_commit(leaf_1)
  1698. transaction.on_commit(leaf_2)
  1699. with self.captureOnCommitCallbacks(execute=True) as callbacks:
  1700. transaction.on_commit(branch_1)
  1701. self.assertEqual(branch_1_call_counter, 1)
  1702. self.assertEqual(branch_2_call_counter, 1)
  1703. self.assertEqual(leaf_1_call_counter, 1)
  1704. self.assertEqual(leaf_2_call_counter, 1)
  1705. self.assertEqual(leaf_3_call_counter, 1)
  1706. self.assertEqual(callbacks, [branch_1, branch_2, leaf_3, leaf_1, leaf_2])
  1707. def test_execute_robust(self):
  1708. class MyException(Exception):
  1709. pass
  1710. def hook():
  1711. self.callback_called = True
  1712. raise MyException("robust callback")
  1713. with self.assertLogs("django.test", "ERROR") as cm:
  1714. with self.captureOnCommitCallbacks(execute=True) as callbacks:
  1715. transaction.on_commit(hook, robust=True)
  1716. self.assertEqual(len(callbacks), 1)
  1717. self.assertIs(self.callback_called, True)
  1718. log_record = cm.records[0]
  1719. self.assertEqual(
  1720. log_record.getMessage(),
  1721. "Error calling CaptureOnCommitCallbacksTests.test_execute_robust.<locals>."
  1722. "hook in on_commit() (robust callback).",
  1723. )
  1724. self.assertIsNotNone(log_record.exc_info)
  1725. raised_exception = log_record.exc_info[1]
  1726. self.assertIsInstance(raised_exception, MyException)
  1727. self.assertEqual(str(raised_exception), "robust callback")
  1728. class DisallowedDatabaseQueriesTests(SimpleTestCase):
  1729. def test_disallowed_database_connections(self):
  1730. expected_message = (
  1731. "Database connections to 'default' are not allowed in SimpleTestCase "
  1732. "subclasses. Either subclass TestCase or TransactionTestCase to "
  1733. "ensure proper test isolation or add 'default' to "
  1734. "test_utils.tests.DisallowedDatabaseQueriesTests.databases to "
  1735. "silence this failure."
  1736. )
  1737. with self.assertRaisesMessage(DatabaseOperationForbidden, expected_message):
  1738. connection.connect()
  1739. with self.assertRaisesMessage(DatabaseOperationForbidden, expected_message):
  1740. connection.temporary_connection()
  1741. def test_disallowed_database_queries(self):
  1742. expected_message = (
  1743. "Database queries to 'default' are not allowed in SimpleTestCase "
  1744. "subclasses. Either subclass TestCase or TransactionTestCase to "
  1745. "ensure proper test isolation or add 'default' to "
  1746. "test_utils.tests.DisallowedDatabaseQueriesTests.databases to "
  1747. "silence this failure."
  1748. )
  1749. with self.assertRaisesMessage(DatabaseOperationForbidden, expected_message):
  1750. Car.objects.first()
  1751. def test_disallowed_database_chunked_cursor_queries(self):
  1752. expected_message = (
  1753. "Database queries to 'default' are not allowed in SimpleTestCase "
  1754. "subclasses. Either subclass TestCase or TransactionTestCase to "
  1755. "ensure proper test isolation or add 'default' to "
  1756. "test_utils.tests.DisallowedDatabaseQueriesTests.databases to "
  1757. "silence this failure."
  1758. )
  1759. with self.assertRaisesMessage(DatabaseOperationForbidden, expected_message):
  1760. next(Car.objects.iterator())
  1761. class AllowedDatabaseQueriesTests(SimpleTestCase):
  1762. databases = {"default"}
  1763. def test_allowed_database_queries(self):
  1764. Car.objects.first()
  1765. def test_allowed_database_chunked_cursor_queries(self):
  1766. next(Car.objects.iterator(), None)
  1767. class DatabaseAliasTests(SimpleTestCase):
  1768. def setUp(self):
  1769. self.addCleanup(setattr, self.__class__, "databases", self.databases)
  1770. def test_no_close_match(self):
  1771. self.__class__.databases = {"void"}
  1772. message = (
  1773. "test_utils.tests.DatabaseAliasTests.databases refers to 'void' which is "
  1774. "not defined in settings.DATABASES."
  1775. )
  1776. with self.assertRaisesMessage(ImproperlyConfigured, message):
  1777. self._validate_databases()
  1778. def test_close_match(self):
  1779. self.__class__.databases = {"defualt"}
  1780. message = (
  1781. "test_utils.tests.DatabaseAliasTests.databases refers to 'defualt' which "
  1782. "is not defined in settings.DATABASES. Did you mean 'default'?"
  1783. )
  1784. with self.assertRaisesMessage(ImproperlyConfigured, message):
  1785. self._validate_databases()
  1786. def test_match(self):
  1787. self.__class__.databases = {"default", "other"}
  1788. self.assertEqual(self._validate_databases(), frozenset({"default", "other"}))
  1789. def test_all(self):
  1790. self.__class__.databases = "__all__"
  1791. self.assertEqual(self._validate_databases(), frozenset(connections))
  1792. @isolate_apps("test_utils", attr_name="class_apps")
  1793. class IsolatedAppsTests(SimpleTestCase):
  1794. def test_installed_apps(self):
  1795. self.assertEqual(
  1796. [app_config.label for app_config in self.class_apps.get_app_configs()],
  1797. ["test_utils"],
  1798. )
  1799. def test_class_decoration(self):
  1800. class ClassDecoration(models.Model):
  1801. pass
  1802. self.assertEqual(ClassDecoration._meta.apps, self.class_apps)
  1803. @isolate_apps("test_utils", kwarg_name="method_apps")
  1804. def test_method_decoration(self, method_apps):
  1805. class MethodDecoration(models.Model):
  1806. pass
  1807. self.assertEqual(MethodDecoration._meta.apps, method_apps)
  1808. def test_context_manager(self):
  1809. with isolate_apps("test_utils") as context_apps:
  1810. class ContextManager(models.Model):
  1811. pass
  1812. self.assertEqual(ContextManager._meta.apps, context_apps)
  1813. @isolate_apps("test_utils", kwarg_name="method_apps")
  1814. def test_nested(self, method_apps):
  1815. class MethodDecoration(models.Model):
  1816. pass
  1817. with isolate_apps("test_utils") as context_apps:
  1818. class ContextManager(models.Model):
  1819. pass
  1820. with isolate_apps("test_utils") as nested_context_apps:
  1821. class NestedContextManager(models.Model):
  1822. pass
  1823. self.assertEqual(MethodDecoration._meta.apps, method_apps)
  1824. self.assertEqual(ContextManager._meta.apps, context_apps)
  1825. self.assertEqual(NestedContextManager._meta.apps, nested_context_apps)
  1826. class DoNothingDecorator(TestContextDecorator):
  1827. def enable(self):
  1828. pass
  1829. def disable(self):
  1830. pass
  1831. class TestContextDecoratorTests(SimpleTestCase):
  1832. @mock.patch.object(DoNothingDecorator, "disable")
  1833. def test_exception_in_setup(self, mock_disable):
  1834. """An exception is setUp() is reraised after disable() is called."""
  1835. class ExceptionInSetUp(unittest.TestCase):
  1836. def setUp(self):
  1837. raise NotImplementedError("reraised")
  1838. decorator = DoNothingDecorator()
  1839. decorated_test_class = decorator.__call__(ExceptionInSetUp)()
  1840. self.assertFalse(mock_disable.called)
  1841. with self.assertRaisesMessage(NotImplementedError, "reraised"):
  1842. decorated_test_class.setUp()
  1843. decorated_test_class.doCleanups()
  1844. self.assertTrue(mock_disable.called)
  1845. def test_cleanups_run_after_tearDown(self):
  1846. calls = []
  1847. class SaveCallsDecorator(TestContextDecorator):
  1848. def enable(self):
  1849. calls.append("enable")
  1850. def disable(self):
  1851. calls.append("disable")
  1852. class AddCleanupInSetUp(unittest.TestCase):
  1853. def setUp(self):
  1854. calls.append("setUp")
  1855. self.addCleanup(lambda: calls.append("cleanup"))
  1856. decorator = SaveCallsDecorator()
  1857. decorated_test_class = decorator.__call__(AddCleanupInSetUp)()
  1858. decorated_test_class.setUp()
  1859. decorated_test_class.tearDown()
  1860. decorated_test_class.doCleanups()
  1861. self.assertEqual(calls, ["enable", "setUp", "cleanup", "disable"])