/tests/modeltests/transactions/tests_25.py
Python | 137 lines | 106 code | 10 blank | 21 comment | 0 complexity | e2e001f9a0b6371af0fc6cdaae6f683b MD5 | raw file
1from __future__ import with_statement 2 3from django.db import connection, transaction, IntegrityError 4from django.test import TransactionTestCase, skipUnlessDBFeature 5 6from models import Reporter 7 8 9class TransactionContextManagerTests(TransactionTestCase): 10 def create_reporter_and_fail(self): 11 Reporter.objects.create(first_name="Bob", last_name="Holtzman") 12 raise Exception 13 14 @skipUnlessDBFeature('supports_transactions') 15 def test_autocommit(self): 16 """ 17 The default behavior is to autocommit after each save() action. 18 """ 19 with self.assertRaises(Exception): 20 self.create_reporter_and_fail() 21 # The object created before the exception still exists 22 self.assertEqual(Reporter.objects.count(), 1) 23 24 @skipUnlessDBFeature('supports_transactions') 25 def test_autocommit_context_manager(self): 26 """ 27 The autocommit context manager works exactly the same as the default 28 behavior. 29 """ 30 with self.assertRaises(Exception): 31 with transaction.autocommit(): 32 self.create_reporter_and_fail() 33 34 self.assertEqual(Reporter.objects.count(), 1) 35 36 @skipUnlessDBFeature('supports_transactions') 37 def test_autocommit_context_manager_with_using(self): 38 """ 39 The autocommit context manager also works with a using argument. 40 """ 41 with self.assertRaises(Exception): 42 with transaction.autocommit(using="default"): 43 self.create_reporter_and_fail() 44 45 self.assertEqual(Reporter.objects.count(), 1) 46 47 @skipUnlessDBFeature('supports_transactions') 48 def test_commit_on_success(self): 49 """ 50 With the commit_on_success context manager, the transaction is only 51 committed if the block doesn't throw an exception. 52 """ 53 with self.assertRaises(Exception): 54 with transaction.commit_on_success(): 55 self.create_reporter_and_fail() 56 57 self.assertEqual(Reporter.objects.count(), 0) 58 59 @skipUnlessDBFeature('supports_transactions') 60 def test_commit_on_success_with_using(self): 61 """ 62 The commit_on_success context manager also works with a using argument. 63 """ 64 with self.assertRaises(Exception): 65 with transaction.commit_on_success(using="default"): 66 self.create_reporter_and_fail() 67 68 self.assertEqual(Reporter.objects.count(), 0) 69 70 @skipUnlessDBFeature('supports_transactions') 71 def test_commit_on_success_succeed(self): 72 """ 73 If there aren't any exceptions, the data will get saved. 74 """ 75 Reporter.objects.create(first_name="Alice", last_name="Smith") 76 with transaction.commit_on_success(): 77 Reporter.objects.filter(first_name="Alice").delete() 78 79 self.assertQuerysetEqual(Reporter.objects.all(), []) 80 81 @skipUnlessDBFeature('supports_transactions') 82 def test_commit_on_success_exit(self): 83 with transaction.autocommit(): 84 with transaction.commit_on_success(): 85 Reporter.objects.create(first_name="Bobby", last_name="Tables") 86 87 # Much more formal 88 r = Reporter.objects.get() 89 r.first_name = "Robert" 90 r.save() 91 92 r = Reporter.objects.get() 93 self.assertEqual(r.first_name, "Robert") 94 95 @skipUnlessDBFeature('supports_transactions') 96 def test_manually_managed(self): 97 """ 98 You can manually manage transactions if you really want to, but you 99 have to remember to commit/rollback. 100 """ 101 with transaction.commit_manually(): 102 Reporter.objects.create(first_name="Libby", last_name="Holtzman") 103 transaction.commit() 104 self.assertEqual(Reporter.objects.count(), 1) 105 106 @skipUnlessDBFeature('supports_transactions') 107 def test_manually_managed_mistake(self): 108 """ 109 If you forget, you'll get bad errors. 110 """ 111 with self.assertRaises(transaction.TransactionManagementError): 112 with transaction.commit_manually(): 113 Reporter.objects.create(first_name="Scott", last_name="Browning") 114 115 @skipUnlessDBFeature('supports_transactions') 116 def test_manually_managed_with_using(self): 117 """ 118 The commit_manually function also works with a using argument. 119 """ 120 with self.assertRaises(transaction.TransactionManagementError): 121 with transaction.commit_manually(using="default"): 122 Reporter.objects.create(first_name="Walter", last_name="Cronkite") 123 124 @skipUnlessDBFeature('requires_rollback_on_dirty_transaction') 125 def test_bad_sql(self): 126 """ 127 Regression for #11900: If a block wrapped by commit_on_success 128 writes a transaction that can't be committed, that transaction should 129 be rolled back. The bug is only visible using the psycopg2 backend, 130 though the fix is generally a good idea. 131 """ 132 with self.assertRaises(IntegrityError): 133 with transaction.commit_on_success(): 134 cursor = connection.cursor() 135 cursor.execute("INSERT INTO transactions_reporter (first_name, last_name) VALUES ('Douglas', 'Adams');") 136 transaction.set_dirty() 137 transaction.rollback()