vis*_*m c 9 python django django-models django-testing
你能不能解释一下TestCase类和TransactionTestCase类之间的区别.我已阅读该文档但其唯一的说法是TestCase在数据库事务中运行测试并使用回滚来"撤消"数据库中的测试,如果需要手动管理测试中的事务,则需要使用django.test.TransactionTestCase .
请你帮我理解一个例子的实际差异吗?我只是想知道TestCase失败的条件是什么?还是回滚是自动发生还是我们必须写回滚声明?
请帮我
TestCase和之间的主要区别TransactionTestCase是TestCase用atomic()块一直包装测试.从文档:
在两个嵌套的atomic()块中包含测试:一个用于整个类,一个用于每个测试
现在假设你有一个方法,如果它没有包含在atomic()块内,应该引发错误.您正在尝试为此编写测试:
def test_your_method_raises_error_without_atomic_block(self):
with self.assertRaises(SomeError):
your_method()
Run Code Online (Sandbox Code Playgroud)
这个测试意外失败!原因是,你猜对了,一直TestCase用atomic()块来包装测试.因此,your_method()不会引发错误,这就是为什么这个测试会失败的原因.在这种情况下,您应该使用TransactionTestCase来进行测试.
select_for_update()就是一个明显的例子:
在自动提交模式下使用select_for_update()在支持SELECT的后端上评估查询集... FOR UPDATE是一个TransactionManagementError错误
使用TestCase类,您无法测试事务中是否正在执行代码块,这在使用select_for_update()时是必需的
如果我们看一下文档select_for_update(),我们会看到一个警告:
尽管select_for_update()通常在自动提交模式下失败,但由于TestCase会自动将每个测试包装在事务中,因此即使在atomic()块之外调用TestCase中的select_for_update()也会(可能意外地)通过而不会引发TransactionManagementError.要正确测试select_for_update(),您应该使用TransactionTestCase.
希望能帮助到你!
小智 5
我想在这里发布一些示例和 django 代码,以便您了解如何TransactionTestCase工作TestCase。
和TransactionTestCase都TestCase继承自SimpleTestCase. 不同之处:
运行测试时,TestCase会检查当前DB是否支持事务功能。如果为 true,将创建一个事务,并且所有测试代码现在都位于“事务块”下。在测试结束时,TestCase将回滚所有内容以保持数据库干净。阅读下面的setUp()和tearDown()函数:
@classmethod
def setUpClass(cls):
super(TestCase, cls).setUpClass()
if not connections_support_transactions():
return
cls.cls_atomics = cls._enter_atomics()
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()
Run Code Online (Sandbox Code Playgroud)
TransactionTestCase但是,不会启动事务。它只是在所有测试完成后刷新数据库。
def _post_teardown(self):
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)
Run Code Online (Sandbox Code Playgroud)
select_for_update()现在使用官方文档中提到的一些非常简单的示例:
class 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)
Run Code Online (Sandbox Code Playgroud)
第一个将提出:
AssertionError:未引发 TransactionManagementError
第二个将顺利通过。
| 归档时间: |
|
| 查看次数: |
3565 次 |
| 最近记录: |