tests.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. """
  2. Tests for django test runner
  3. """
  4. import collections.abc
  5. import unittest
  6. from unittest import mock
  7. from admin_scripts.tests import AdminScriptTestCase
  8. from django import db
  9. from django.conf import settings
  10. from django.core.exceptions import ImproperlyConfigured
  11. from django.core.management import call_command
  12. from django.core.management.base import SystemCheckError
  13. from django.test import (
  14. SimpleTestCase, TransactionTestCase, skipUnlessDBFeature,
  15. )
  16. from django.test.runner import (
  17. DiscoverRunner, Shuffler, reorder_test_bin, reorder_tests, shuffle_tests,
  18. )
  19. from django.test.testcases import connections_support_transactions
  20. from django.test.utils import (
  21. captured_stderr, dependency_ordered, get_unique_databases_and_mirrors,
  22. iter_test_cases,
  23. )
  24. from django.utils.deprecation import RemovedInDjango50Warning
  25. from .models import B, Person, Through
  26. class MySuite:
  27. def __init__(self):
  28. self.tests = []
  29. def addTest(self, test):
  30. self.tests.append(test)
  31. def __iter__(self):
  32. yield from self.tests
  33. class TestSuiteTests(SimpleTestCase):
  34. def build_test_suite(self, test_classes, suite=None, suite_class=None):
  35. if suite_class is None:
  36. suite_class = unittest.TestSuite
  37. if suite is None:
  38. suite = suite_class()
  39. loader = unittest.defaultTestLoader
  40. for test_class in test_classes:
  41. tests = loader.loadTestsFromTestCase(test_class)
  42. subsuite = suite_class()
  43. # Only use addTest() to simplify testing a custom TestSuite.
  44. for test in tests:
  45. subsuite.addTest(test)
  46. suite.addTest(subsuite)
  47. return suite
  48. def make_test_suite(self, suite=None, suite_class=None):
  49. class Tests1(unittest.TestCase):
  50. def test1(self):
  51. pass
  52. def test2(self):
  53. pass
  54. class Tests2(unittest.TestCase):
  55. def test1(self):
  56. pass
  57. def test2(self):
  58. pass
  59. return self.build_test_suite(
  60. (Tests1, Tests2),
  61. suite=suite,
  62. suite_class=suite_class,
  63. )
  64. def assertTestNames(self, tests, expected):
  65. # Each test.id() has a form like the following:
  66. # "test_runner.tests.IterTestCasesTests.test_iter_test_cases.<locals>.Tests1.test1".
  67. # It suffices to check only the last two parts.
  68. names = ['.'.join(test.id().split('.')[-2:]) for test in tests]
  69. self.assertEqual(names, expected)
  70. def test_iter_test_cases_basic(self):
  71. suite = self.make_test_suite()
  72. tests = iter_test_cases(suite)
  73. self.assertTestNames(tests, expected=[
  74. 'Tests1.test1', 'Tests1.test2', 'Tests2.test1', 'Tests2.test2',
  75. ])
  76. def test_iter_test_cases_string_input(self):
  77. msg = (
  78. "Test 'a' must be a test case or test suite not string (was found "
  79. "in 'abc')."
  80. )
  81. with self.assertRaisesMessage(TypeError, msg):
  82. list(iter_test_cases('abc'))
  83. def test_iter_test_cases_iterable_of_tests(self):
  84. class Tests(unittest.TestCase):
  85. def test1(self):
  86. pass
  87. def test2(self):
  88. pass
  89. tests = list(unittest.defaultTestLoader.loadTestsFromTestCase(Tests))
  90. actual_tests = iter_test_cases(tests)
  91. self.assertTestNames(actual_tests, expected=[
  92. 'Tests.test1', 'Tests.test2',
  93. ])
  94. def test_iter_test_cases_custom_test_suite_class(self):
  95. suite = self.make_test_suite(suite_class=MySuite)
  96. tests = iter_test_cases(suite)
  97. self.assertTestNames(tests, expected=[
  98. 'Tests1.test1', 'Tests1.test2', 'Tests2.test1', 'Tests2.test2',
  99. ])
  100. def test_iter_test_cases_mixed_test_suite_classes(self):
  101. suite = self.make_test_suite(suite=MySuite())
  102. child_suite = list(suite)[0]
  103. self.assertNotIsInstance(child_suite, MySuite)
  104. tests = list(iter_test_cases(suite))
  105. self.assertEqual(len(tests), 4)
  106. self.assertNotIsInstance(tests[0], unittest.TestSuite)
  107. def make_tests(self):
  108. """Return an iterable of tests."""
  109. suite = self.make_test_suite()
  110. tests = list(iter_test_cases(suite))
  111. return tests
  112. def test_shuffle_tests(self):
  113. tests = self.make_tests()
  114. # Choose a seed that shuffles both the classes and methods.
  115. shuffler = Shuffler(seed=9)
  116. shuffled_tests = shuffle_tests(tests, shuffler)
  117. self.assertIsInstance(shuffled_tests, collections.abc.Iterator)
  118. self.assertTestNames(shuffled_tests, expected=[
  119. 'Tests2.test1', 'Tests2.test2', 'Tests1.test2', 'Tests1.test1',
  120. ])
  121. def test_reorder_test_bin_no_arguments(self):
  122. tests = self.make_tests()
  123. reordered_tests = reorder_test_bin(tests)
  124. self.assertIsInstance(reordered_tests, collections.abc.Iterator)
  125. self.assertTestNames(reordered_tests, expected=[
  126. 'Tests1.test1', 'Tests1.test2', 'Tests2.test1', 'Tests2.test2',
  127. ])
  128. def test_reorder_test_bin_reverse(self):
  129. tests = self.make_tests()
  130. reordered_tests = reorder_test_bin(tests, reverse=True)
  131. self.assertIsInstance(reordered_tests, collections.abc.Iterator)
  132. self.assertTestNames(reordered_tests, expected=[
  133. 'Tests2.test2', 'Tests2.test1', 'Tests1.test2', 'Tests1.test1',
  134. ])
  135. def test_reorder_test_bin_random(self):
  136. tests = self.make_tests()
  137. # Choose a seed that shuffles both the classes and methods.
  138. shuffler = Shuffler(seed=9)
  139. reordered_tests = reorder_test_bin(tests, shuffler=shuffler)
  140. self.assertIsInstance(reordered_tests, collections.abc.Iterator)
  141. self.assertTestNames(reordered_tests, expected=[
  142. 'Tests2.test1', 'Tests2.test2', 'Tests1.test2', 'Tests1.test1',
  143. ])
  144. def test_reorder_test_bin_random_and_reverse(self):
  145. tests = self.make_tests()
  146. # Choose a seed that shuffles both the classes and methods.
  147. shuffler = Shuffler(seed=9)
  148. reordered_tests = reorder_test_bin(tests, shuffler=shuffler, reverse=True)
  149. self.assertIsInstance(reordered_tests, collections.abc.Iterator)
  150. self.assertTestNames(reordered_tests, expected=[
  151. 'Tests1.test1', 'Tests1.test2', 'Tests2.test2', 'Tests2.test1',
  152. ])
  153. def test_reorder_tests_same_type_consecutive(self):
  154. """Tests of the same type are made consecutive."""
  155. tests = self.make_tests()
  156. # Move the last item to the front.
  157. tests.insert(0, tests.pop())
  158. self.assertTestNames(tests, expected=[
  159. 'Tests2.test2', 'Tests1.test1', 'Tests1.test2', 'Tests2.test1',
  160. ])
  161. reordered_tests = reorder_tests(tests, classes=[])
  162. self.assertTestNames(reordered_tests, expected=[
  163. 'Tests2.test2', 'Tests2.test1', 'Tests1.test1', 'Tests1.test2',
  164. ])
  165. def test_reorder_tests_random(self):
  166. tests = self.make_tests()
  167. # Choose a seed that shuffles both the classes and methods.
  168. shuffler = Shuffler(seed=9)
  169. reordered_tests = reorder_tests(tests, classes=[], shuffler=shuffler)
  170. self.assertIsInstance(reordered_tests, collections.abc.Iterator)
  171. self.assertTestNames(reordered_tests, expected=[
  172. 'Tests2.test1', 'Tests2.test2', 'Tests1.test2', 'Tests1.test1',
  173. ])
  174. def test_reorder_tests_random_mixed_classes(self):
  175. tests = self.make_tests()
  176. # Move the last item to the front.
  177. tests.insert(0, tests.pop())
  178. shuffler = Shuffler(seed=9)
  179. self.assertTestNames(tests, expected=[
  180. 'Tests2.test2', 'Tests1.test1', 'Tests1.test2', 'Tests2.test1',
  181. ])
  182. reordered_tests = reorder_tests(tests, classes=[], shuffler=shuffler)
  183. self.assertTestNames(reordered_tests, expected=[
  184. 'Tests2.test1', 'Tests2.test2', 'Tests1.test2', 'Tests1.test1',
  185. ])
  186. def test_reorder_tests_reverse_with_duplicates(self):
  187. class Tests1(unittest.TestCase):
  188. def test1(self):
  189. pass
  190. class Tests2(unittest.TestCase):
  191. def test2(self):
  192. pass
  193. def test3(self):
  194. pass
  195. suite = self.build_test_suite((Tests1, Tests2))
  196. subsuite = list(suite)[0]
  197. suite.addTest(subsuite)
  198. tests = list(iter_test_cases(suite))
  199. self.assertTestNames(tests, expected=[
  200. 'Tests1.test1', 'Tests2.test2', 'Tests2.test3', 'Tests1.test1',
  201. ])
  202. reordered_tests = reorder_tests(tests, classes=[])
  203. self.assertTestNames(reordered_tests, expected=[
  204. 'Tests1.test1', 'Tests2.test2', 'Tests2.test3',
  205. ])
  206. reordered_tests = reorder_tests(tests, classes=[], reverse=True)
  207. self.assertTestNames(reordered_tests, expected=[
  208. 'Tests2.test3', 'Tests2.test2', 'Tests1.test1',
  209. ])
  210. class DependencyOrderingTests(unittest.TestCase):
  211. def test_simple_dependencies(self):
  212. raw = [
  213. ('s1', ('s1_db', ['alpha'])),
  214. ('s2', ('s2_db', ['bravo'])),
  215. ('s3', ('s3_db', ['charlie'])),
  216. ]
  217. dependencies = {
  218. 'alpha': ['charlie'],
  219. 'bravo': ['charlie'],
  220. }
  221. ordered = dependency_ordered(raw, dependencies=dependencies)
  222. ordered_sigs = [sig for sig, value in ordered]
  223. self.assertIn('s1', ordered_sigs)
  224. self.assertIn('s2', ordered_sigs)
  225. self.assertIn('s3', ordered_sigs)
  226. self.assertLess(ordered_sigs.index('s3'), ordered_sigs.index('s1'))
  227. self.assertLess(ordered_sigs.index('s3'), ordered_sigs.index('s2'))
  228. def test_chained_dependencies(self):
  229. raw = [
  230. ('s1', ('s1_db', ['alpha'])),
  231. ('s2', ('s2_db', ['bravo'])),
  232. ('s3', ('s3_db', ['charlie'])),
  233. ]
  234. dependencies = {
  235. 'alpha': ['bravo'],
  236. 'bravo': ['charlie'],
  237. }
  238. ordered = dependency_ordered(raw, dependencies=dependencies)
  239. ordered_sigs = [sig for sig, value in ordered]
  240. self.assertIn('s1', ordered_sigs)
  241. self.assertIn('s2', ordered_sigs)
  242. self.assertIn('s3', ordered_sigs)
  243. # Explicit dependencies
  244. self.assertLess(ordered_sigs.index('s2'), ordered_sigs.index('s1'))
  245. self.assertLess(ordered_sigs.index('s3'), ordered_sigs.index('s2'))
  246. # Implied dependencies
  247. self.assertLess(ordered_sigs.index('s3'), ordered_sigs.index('s1'))
  248. def test_multiple_dependencies(self):
  249. raw = [
  250. ('s1', ('s1_db', ['alpha'])),
  251. ('s2', ('s2_db', ['bravo'])),
  252. ('s3', ('s3_db', ['charlie'])),
  253. ('s4', ('s4_db', ['delta'])),
  254. ]
  255. dependencies = {
  256. 'alpha': ['bravo', 'delta'],
  257. 'bravo': ['charlie'],
  258. 'delta': ['charlie'],
  259. }
  260. ordered = dependency_ordered(raw, dependencies=dependencies)
  261. ordered_sigs = [sig for sig, aliases in ordered]
  262. self.assertIn('s1', ordered_sigs)
  263. self.assertIn('s2', ordered_sigs)
  264. self.assertIn('s3', ordered_sigs)
  265. self.assertIn('s4', ordered_sigs)
  266. # Explicit dependencies
  267. self.assertLess(ordered_sigs.index('s2'), ordered_sigs.index('s1'))
  268. self.assertLess(ordered_sigs.index('s4'), ordered_sigs.index('s1'))
  269. self.assertLess(ordered_sigs.index('s3'), ordered_sigs.index('s2'))
  270. self.assertLess(ordered_sigs.index('s3'), ordered_sigs.index('s4'))
  271. # Implicit dependencies
  272. self.assertLess(ordered_sigs.index('s3'), ordered_sigs.index('s1'))
  273. def test_circular_dependencies(self):
  274. raw = [
  275. ('s1', ('s1_db', ['alpha'])),
  276. ('s2', ('s2_db', ['bravo'])),
  277. ]
  278. dependencies = {
  279. 'bravo': ['alpha'],
  280. 'alpha': ['bravo'],
  281. }
  282. with self.assertRaises(ImproperlyConfigured):
  283. dependency_ordered(raw, dependencies=dependencies)
  284. def test_own_alias_dependency(self):
  285. raw = [
  286. ('s1', ('s1_db', ['alpha', 'bravo']))
  287. ]
  288. dependencies = {
  289. 'alpha': ['bravo']
  290. }
  291. with self.assertRaises(ImproperlyConfigured):
  292. dependency_ordered(raw, dependencies=dependencies)
  293. # reordering aliases shouldn't matter
  294. raw = [
  295. ('s1', ('s1_db', ['bravo', 'alpha']))
  296. ]
  297. with self.assertRaises(ImproperlyConfigured):
  298. dependency_ordered(raw, dependencies=dependencies)
  299. class MockTestRunner:
  300. def __init__(self, *args, **kwargs):
  301. pass
  302. MockTestRunner.run_tests = mock.Mock(return_value=[])
  303. class ManageCommandTests(unittest.TestCase):
  304. def test_custom_test_runner(self):
  305. call_command('test', 'sites',
  306. testrunner='test_runner.tests.MockTestRunner')
  307. MockTestRunner.run_tests.assert_called_with(('sites',))
  308. def test_bad_test_runner(self):
  309. with self.assertRaises(AttributeError):
  310. call_command('test', 'sites', testrunner='test_runner.NonexistentRunner')
  311. def test_time_recorded(self):
  312. with captured_stderr() as stderr:
  313. call_command('test', '--timing', 'sites', testrunner='test_runner.tests.MockTestRunner')
  314. self.assertIn('Total run took', stderr.getvalue())
  315. class CustomTestRunnerOptionsSettingsTests(AdminScriptTestCase):
  316. """
  317. Custom runners can add command line arguments. The runner is specified
  318. through a settings file.
  319. """
  320. def setUp(self):
  321. super().setUp()
  322. settings = {
  323. 'TEST_RUNNER': '\'test_runner.runner.CustomOptionsTestRunner\'',
  324. }
  325. self.write_settings('settings.py', sdict=settings)
  326. def test_default_options(self):
  327. args = ['test', '--settings=test_project.settings']
  328. out, err = self.run_django_admin(args)
  329. self.assertNoOutput(err)
  330. self.assertOutput(out, '1:2:3')
  331. def test_default_and_given_options(self):
  332. args = ['test', '--settings=test_project.settings', '--option_b=foo']
  333. out, err = self.run_django_admin(args)
  334. self.assertNoOutput(err)
  335. self.assertOutput(out, '1:foo:3')
  336. def test_option_name_and_value_separated(self):
  337. args = ['test', '--settings=test_project.settings', '--option_b', 'foo']
  338. out, err = self.run_django_admin(args)
  339. self.assertNoOutput(err)
  340. self.assertOutput(out, '1:foo:3')
  341. def test_all_options_given(self):
  342. args = ['test', '--settings=test_project.settings', '--option_a=bar',
  343. '--option_b=foo', '--option_c=31337']
  344. out, err = self.run_django_admin(args)
  345. self.assertNoOutput(err)
  346. self.assertOutput(out, 'bar:foo:31337')
  347. class CustomTestRunnerOptionsCmdlineTests(AdminScriptTestCase):
  348. """
  349. Custom runners can add command line arguments when the runner is specified
  350. using --testrunner.
  351. """
  352. def setUp(self):
  353. super().setUp()
  354. self.write_settings('settings.py')
  355. def test_testrunner_option(self):
  356. args = [
  357. 'test', '--testrunner', 'test_runner.runner.CustomOptionsTestRunner',
  358. '--option_a=bar', '--option_b=foo', '--option_c=31337'
  359. ]
  360. out, err = self.run_django_admin(args, 'test_project.settings')
  361. self.assertNoOutput(err)
  362. self.assertOutput(out, 'bar:foo:31337')
  363. def test_testrunner_equals(self):
  364. args = [
  365. 'test', '--testrunner=test_runner.runner.CustomOptionsTestRunner',
  366. '--option_a=bar', '--option_b=foo', '--option_c=31337'
  367. ]
  368. out, err = self.run_django_admin(args, 'test_project.settings')
  369. self.assertNoOutput(err)
  370. self.assertOutput(out, 'bar:foo:31337')
  371. def test_no_testrunner(self):
  372. args = ['test', '--testrunner']
  373. out, err = self.run_django_admin(args, 'test_project.settings')
  374. self.assertIn('usage', err)
  375. self.assertNotIn('Traceback', err)
  376. self.assertNoOutput(out)
  377. class Ticket17477RegressionTests(AdminScriptTestCase):
  378. def setUp(self):
  379. super().setUp()
  380. self.write_settings('settings.py')
  381. def test_ticket_17477(self):
  382. """'manage.py help test' works after r16352."""
  383. args = ['help', 'test']
  384. out, err = self.run_manage(args)
  385. self.assertNoOutput(err)
  386. class SQLiteInMemoryTestDbs(TransactionTestCase):
  387. available_apps = ['test_runner']
  388. databases = {'default', 'other'}
  389. @unittest.skipUnless(all(db.connections[conn].vendor == 'sqlite' for conn in db.connections),
  390. "This is an sqlite-specific issue")
  391. def test_transaction_support(self):
  392. # Assert connections mocking is appropriately applied by preventing
  393. # any attempts at calling create_test_db on the global connection
  394. # objects.
  395. for connection in db.connections.all():
  396. create_test_db = mock.patch.object(
  397. connection.creation,
  398. 'create_test_db',
  399. side_effect=AssertionError("Global connection object shouldn't be manipulated.")
  400. )
  401. create_test_db.start()
  402. self.addCleanup(create_test_db.stop)
  403. for option_key, option_value in (
  404. ('NAME', ':memory:'), ('TEST', {'NAME': ':memory:'})):
  405. tested_connections = db.ConnectionHandler({
  406. 'default': {
  407. 'ENGINE': 'django.db.backends.sqlite3',
  408. option_key: option_value,
  409. },
  410. 'other': {
  411. 'ENGINE': 'django.db.backends.sqlite3',
  412. option_key: option_value,
  413. },
  414. })
  415. with mock.patch('django.test.utils.connections', new=tested_connections):
  416. other = tested_connections['other']
  417. DiscoverRunner(verbosity=0).setup_databases()
  418. msg = (
  419. "DATABASES setting '%s' option set to sqlite3's ':memory:' value "
  420. "shouldn't interfere with transaction support detection." % option_key
  421. )
  422. # Transaction support is properly initialized for the 'other' DB.
  423. self.assertTrue(other.features.supports_transactions, msg)
  424. # And all the DBs report that they support transactions.
  425. self.assertTrue(connections_support_transactions(), msg)
  426. class DummyBackendTest(unittest.TestCase):
  427. def test_setup_databases(self):
  428. """
  429. setup_databases() doesn't fail with dummy database backend.
  430. """
  431. tested_connections = db.ConnectionHandler({})
  432. with mock.patch('django.test.utils.connections', new=tested_connections):
  433. runner_instance = DiscoverRunner(verbosity=0)
  434. old_config = runner_instance.setup_databases()
  435. runner_instance.teardown_databases(old_config)
  436. class AliasedDefaultTestSetupTest(unittest.TestCase):
  437. def test_setup_aliased_default_database(self):
  438. """
  439. setup_databases() doesn't fail when 'default' is aliased
  440. """
  441. tested_connections = db.ConnectionHandler({
  442. 'default': {
  443. 'NAME': 'dummy'
  444. },
  445. 'aliased': {
  446. 'NAME': 'dummy'
  447. }
  448. })
  449. with mock.patch('django.test.utils.connections', new=tested_connections):
  450. runner_instance = DiscoverRunner(verbosity=0)
  451. old_config = runner_instance.setup_databases()
  452. runner_instance.teardown_databases(old_config)
  453. class SetupDatabasesTests(SimpleTestCase):
  454. def setUp(self):
  455. self.runner_instance = DiscoverRunner(verbosity=0)
  456. def test_setup_aliased_databases(self):
  457. tested_connections = db.ConnectionHandler({
  458. 'default': {
  459. 'ENGINE': 'django.db.backends.dummy',
  460. 'NAME': 'dbname',
  461. },
  462. 'other': {
  463. 'ENGINE': 'django.db.backends.dummy',
  464. 'NAME': 'dbname',
  465. }
  466. })
  467. with mock.patch('django.db.backends.dummy.base.DatabaseWrapper.creation_class') as mocked_db_creation:
  468. with mock.patch('django.test.utils.connections', new=tested_connections):
  469. old_config = self.runner_instance.setup_databases()
  470. self.runner_instance.teardown_databases(old_config)
  471. mocked_db_creation.return_value.destroy_test_db.assert_called_once_with('dbname', 0, False)
  472. def test_setup_test_database_aliases(self):
  473. """
  474. The default database must be the first because data migrations
  475. use the default alias by default.
  476. """
  477. tested_connections = db.ConnectionHandler({
  478. 'other': {
  479. 'ENGINE': 'django.db.backends.dummy',
  480. 'NAME': 'dbname',
  481. },
  482. 'default': {
  483. 'ENGINE': 'django.db.backends.dummy',
  484. 'NAME': 'dbname',
  485. }
  486. })
  487. with mock.patch('django.test.utils.connections', new=tested_connections):
  488. test_databases, _ = get_unique_databases_and_mirrors()
  489. self.assertEqual(
  490. test_databases,
  491. {
  492. ('', '', 'django.db.backends.dummy', 'test_dbname'): (
  493. 'dbname',
  494. ['default', 'other'],
  495. ),
  496. },
  497. )
  498. def test_destroy_test_db_restores_db_name(self):
  499. tested_connections = db.ConnectionHandler({
  500. 'default': {
  501. 'ENGINE': settings.DATABASES[db.DEFAULT_DB_ALIAS]["ENGINE"],
  502. 'NAME': 'xxx_test_database',
  503. },
  504. })
  505. # Using the real current name as old_name to not mess with the test suite.
  506. old_name = settings.DATABASES[db.DEFAULT_DB_ALIAS]["NAME"]
  507. with mock.patch('django.db.connections', new=tested_connections):
  508. tested_connections['default'].creation.destroy_test_db(old_name, verbosity=0, keepdb=True)
  509. self.assertEqual(tested_connections['default'].settings_dict["NAME"], old_name)
  510. def test_serialization(self):
  511. tested_connections = db.ConnectionHandler({
  512. 'default': {
  513. 'ENGINE': 'django.db.backends.dummy',
  514. },
  515. })
  516. with mock.patch('django.db.backends.dummy.base.DatabaseWrapper.creation_class') as mocked_db_creation:
  517. with mock.patch('django.test.utils.connections', new=tested_connections):
  518. self.runner_instance.setup_databases()
  519. mocked_db_creation.return_value.create_test_db.assert_called_once_with(
  520. verbosity=0, autoclobber=False, serialize=True, keepdb=False
  521. )
  522. def test_serialized_off(self):
  523. tested_connections = db.ConnectionHandler({
  524. 'default': {
  525. 'ENGINE': 'django.db.backends.dummy',
  526. 'TEST': {'SERIALIZE': False},
  527. },
  528. })
  529. msg = (
  530. 'The SERIALIZE test database setting is deprecated as it can be '
  531. 'inferred from the TestCase/TransactionTestCase.databases that '
  532. 'enable the serialized_rollback feature.'
  533. )
  534. with mock.patch('django.db.backends.dummy.base.DatabaseWrapper.creation_class') as mocked_db_creation:
  535. with mock.patch('django.test.utils.connections', new=tested_connections):
  536. with self.assertWarnsMessage(RemovedInDjango50Warning, msg):
  537. self.runner_instance.setup_databases()
  538. mocked_db_creation.return_value.create_test_db.assert_called_once_with(
  539. verbosity=0, autoclobber=False, serialize=False, keepdb=False
  540. )
  541. @skipUnlessDBFeature('supports_sequence_reset')
  542. class AutoIncrementResetTest(TransactionTestCase):
  543. """
  544. Creating the same models in different test methods receive the same PK
  545. values since the sequences are reset before each test method.
  546. """
  547. available_apps = ['test_runner']
  548. reset_sequences = True
  549. def _test(self):
  550. # Regular model
  551. p = Person.objects.create(first_name='Jack', last_name='Smith')
  552. self.assertEqual(p.pk, 1)
  553. # Auto-created many-to-many through model
  554. p.friends.add(Person.objects.create(first_name='Jacky', last_name='Smith'))
  555. self.assertEqual(p.friends.through.objects.first().pk, 1)
  556. # Many-to-many through model
  557. b = B.objects.create()
  558. t = Through.objects.create(person=p, b=b)
  559. self.assertEqual(t.pk, 1)
  560. def test_autoincrement_reset1(self):
  561. self._test()
  562. def test_autoincrement_reset2(self):
  563. self._test()
  564. class EmptyDefaultDatabaseTest(unittest.TestCase):
  565. def test_empty_default_database(self):
  566. """
  567. An empty default database in settings does not raise an ImproperlyConfigured
  568. error when running a unit test that does not use a database.
  569. """
  570. tested_connections = db.ConnectionHandler({'default': {}})
  571. with mock.patch('django.db.connections', new=tested_connections):
  572. connection = tested_connections[db.utils.DEFAULT_DB_ALIAS]
  573. self.assertEqual(connection.settings_dict['ENGINE'], 'django.db.backends.dummy')
  574. connections_support_transactions()
  575. class RunTestsExceptionHandlingTests(unittest.TestCase):
  576. def test_run_checks_raises(self):
  577. """
  578. Teardown functions are run when run_checks() raises SystemCheckError.
  579. """
  580. with mock.patch('django.test.runner.DiscoverRunner.setup_test_environment'), \
  581. mock.patch('django.test.runner.DiscoverRunner.setup_databases'), \
  582. mock.patch('django.test.runner.DiscoverRunner.build_suite'), \
  583. mock.patch('django.test.runner.DiscoverRunner.run_checks', side_effect=SystemCheckError), \
  584. mock.patch('django.test.runner.DiscoverRunner.teardown_databases') as teardown_databases, \
  585. mock.patch('django.test.runner.DiscoverRunner.teardown_test_environment') as teardown_test_environment:
  586. runner = DiscoverRunner(verbosity=0, interactive=False)
  587. with self.assertRaises(SystemCheckError):
  588. runner.run_tests(['test_runner_apps.sample.tests_sample.TestDjangoTestCase'])
  589. self.assertTrue(teardown_databases.called)
  590. self.assertTrue(teardown_test_environment.called)
  591. def test_run_checks_raises_and_teardown_raises(self):
  592. """
  593. SystemCheckError is surfaced when run_checks() raises SystemCheckError
  594. and teardown databases() raises ValueError.
  595. """
  596. with mock.patch('django.test.runner.DiscoverRunner.setup_test_environment'), \
  597. mock.patch('django.test.runner.DiscoverRunner.setup_databases'), \
  598. mock.patch('django.test.runner.DiscoverRunner.build_suite'), \
  599. mock.patch('django.test.runner.DiscoverRunner.run_checks', side_effect=SystemCheckError), \
  600. mock.patch('django.test.runner.DiscoverRunner.teardown_databases', side_effect=ValueError) \
  601. as teardown_databases, \
  602. mock.patch('django.test.runner.DiscoverRunner.teardown_test_environment') as teardown_test_environment:
  603. runner = DiscoverRunner(verbosity=0, interactive=False)
  604. with self.assertRaises(SystemCheckError):
  605. runner.run_tests(['test_runner_apps.sample.tests_sample.TestDjangoTestCase'])
  606. self.assertTrue(teardown_databases.called)
  607. self.assertFalse(teardown_test_environment.called)
  608. def test_run_checks_passes_and_teardown_raises(self):
  609. """
  610. Exceptions on teardown are surfaced if no exceptions happen during
  611. run_checks().
  612. """
  613. with mock.patch('django.test.runner.DiscoverRunner.setup_test_environment'), \
  614. mock.patch('django.test.runner.DiscoverRunner.setup_databases'), \
  615. mock.patch('django.test.runner.DiscoverRunner.build_suite'), \
  616. mock.patch('django.test.runner.DiscoverRunner.run_checks'), \
  617. mock.patch('django.test.runner.DiscoverRunner.teardown_databases', side_effect=ValueError) \
  618. as teardown_databases, \
  619. mock.patch('django.test.runner.DiscoverRunner.teardown_test_environment') as teardown_test_environment:
  620. runner = DiscoverRunner(verbosity=0, interactive=False)
  621. with self.assertRaises(ValueError):
  622. # Suppress the output when running TestDjangoTestCase.
  623. with mock.patch('sys.stderr'):
  624. runner.run_tests(['test_runner_apps.sample.tests_sample.TestDjangoTestCase'])
  625. self.assertTrue(teardown_databases.called)
  626. self.assertFalse(teardown_test_environment.called)
  627. # RemovedInDjango50Warning
  628. class NoOpTestRunner(DiscoverRunner):
  629. def setup_test_environment(self, **kwargs):
  630. return
  631. def setup_databases(self, **kwargs):
  632. return
  633. def run_checks(self, databases):
  634. return
  635. def teardown_databases(self, old_config, **kwargs):
  636. return
  637. def teardown_test_environment(self, **kwargs):
  638. return
  639. class DiscoverRunnerExtraTestsDeprecationTests(SimpleTestCase):
  640. msg = 'The extra_tests argument is deprecated.'
  641. def get_runner(self):
  642. return NoOpTestRunner(verbosity=0, interactive=False)
  643. def test_extra_tests_build_suite(self):
  644. runner = self.get_runner()
  645. with self.assertWarnsMessage(RemovedInDjango50Warning, self.msg):
  646. runner.build_suite(extra_tests=[])
  647. def test_extra_tests_run_tests(self):
  648. runner = self.get_runner()
  649. with captured_stderr():
  650. with self.assertWarnsMessage(RemovedInDjango50Warning, self.msg):
  651. runner.run_tests(
  652. test_labels=['test_runner_apps.sample.tests_sample.EmptyTestCase'],
  653. extra_tests=[],
  654. )