TestCase与TransactionTestCase都是继承自SimpleTestCase,两者主要的区别在于:TestCase在测试开始时,判断当前连接的数据库是否支持事务特性,如支持,则开启事务操作;在测试结束时,同样判断是否支持事务特性,如支持,执行事务回滚,然后关闭所有链接。
具体setUpClass与tearDownClass方法如下:
@classmethod def setUpClass(cls): super(TestCase, cls).setUpClass() if not connections_support_transactions(): # 事务支持判断 return cls.cls_atomics = cls._enter_atomics() # 开启事务,TestCase中测试代码均处于此事务Block中 if cls.fixtures: for db_name in cls._databases_names(include_mirrors=False): try: call_command('loaddata', *cls.fixtures, **{ 'verbosity': 0, 'commit': False, 'database': db_name, }) except Exception: cls._rollback_atomics(cls.cls_atomics) raise cls.setUpTestData() @classmethod def tearDownClass(cls): if connections_support_transactions(): # 事务支持判断 cls._rollback_atomics(cls.cls_atomics) # 回滚所有操作 for conn in connections.all(): # 关闭所有链接 conn.close() super(TestCase, cls).tearDownClass()TransactionTestCase与TestCase不同,在此测试类中并不开启事务块,测试结束时通过进行Fush操作清空数据。此类没有重写SimpleTestCase的setUp和tearDown方法,只修改了_post_teardown等如下:
f _post_teardown(self): """ * 堆代码 duidaima.com * 清空数据库的内容 * 关闭链接 """ try: self._fixture_teardown() super(TransactionTestCase, self)._post_teardown() if self._should_reload_connections(): for conn in connections.all(): conn.close() finally: if self.available_apps is not None: apps.unset_available_apps() setting_changed.send(sender=settings._wrapped.__class__, setting='INSTALLED_APPS', value=settings.INSTALLED_APPS, enter=False) def _fixture_teardown(self): for db_name in self._databases_names(include_mirrors=False): call_command('flush', verbosity=0, interactive=False, database=db_name, reset_sequences=False, allow_cascade=self.available_apps is not None, inhibit_post_migrate=self.available_apps is not None)在事务方面的区别使得:使用TestCase时,如果被测试代码中出现必须在事务块中执行的代码,则会抛出异常,如官方举例的select_for_update():
SampleTestCase(TestCase): def setUp(self): Sample.objects.create(**{'field1': 'value1, 'field2': 'value2'}) def test_difference_testcase(self): sample = Sample.objects.select_for_update().filter() print(sample) class SampleTransactionTestCase(TransactionTestCase): def setUp(self): Sample.objects.create(**{'field1': 'value1, 'field2': 'value2'}) def test_difference_transactiontestcase(self): sample = Sample.objects.select_for_update().filter() print(sample)第一个TestCase会抛出异常:
AssertionError: TransactionManagementError not raised第二个TTC会通过测试。