强制 Django 测试将模型写入数据库
force Django tests to write models into database
我正在建立一个非常简单的 Django 项目和一个非常简单的测试,例如:
def test_name(self):
t = Thing.objects.create(name='a')
print(t.id)
import time
time.sleep(30)
self.assertEqual('a', t.name)
测试当然通过了,但是数据库(TEST
数据库)并没有填充我的 Thing
模型信息,尽管我实际上可以看到它的 id
你可以看到我的脚本。
当我连接到数据库时,Thing
table 总是空的(我也在文档中看到了一些关于它的评论)。
现在,我如何告诉 Django 实际填充数据?我正在使用 mysql,并检查完整的日志,我看到 Django 在填充数据(未提交)之前创建了一个 SAVEPOINT
,一旦测试通过,它就会返回到之前的 SAVEPOINT
].
我正在使用:
Django==2.0.1
mysqlclient==1.3.12
pytest==3.3.2
pytest-django==3.1.2
我希望 Django 实际填充 TEST
数据库,使用我的测试信息并在最后删除该数据库,这就是为什么我假设 Django 正在创建一个全新的数据库只是为了测试。
如果您正在使用 django TestCase class,它是 TransactionTestCase class 的子class,数据库将始终重置为原始状态。
https://docs.djangoproject.com/en/2.0/topics/testing/tools/#django.test.TestCase
https://docs.djangoproject.com/en/2.0/topics/testing/tools/#django.test.TransactionTestCase
用于纯函数测试的 django.test.TransactionTestCase
的挂件是标记
pytest.mark.django_db(transaction=True)
来自 pytest-django
。示例(使用 sqlite3
后端):
@pytest.mark.django_db(transaction=True)
def test_model_written_to_db():
obj = MyModel.objects.create(name='foo')
assert obj.id == 1
conn = sqlite3.connect('/tmp/mytestdatabase.sqlite3')
cur = conn.cursor()
cur.execute("SELECT * FROM backend_mymodel")
assert len(cur.fetchall()) == 1
如果您想将标记自动应用于所有测试,您可以使用自定义 pytest_collection_modifyitems
挂钩来实现。在你的 conftest.py
:
import pytest
def pytest_collection_modifyitems(items):
for item in items:
item.add_marker(pytest.mark.django_db(transaction=True))
现在您可以从上面的测试中删除 pytest.mark.django_db
标记,它的行为仍然相同。
但是,自定义挂钩或 pytest
固定装置不适用于 unittest
样式的测试用例子类化 django.test.TestCase
,因此您最好的选择确实是子类化 django.test.TransactionTestCase
, 按照建议 Ghariani Mohamed in .
我正在建立一个非常简单的 Django 项目和一个非常简单的测试,例如:
def test_name(self):
t = Thing.objects.create(name='a')
print(t.id)
import time
time.sleep(30)
self.assertEqual('a', t.name)
测试当然通过了,但是数据库(TEST
数据库)并没有填充我的 Thing
模型信息,尽管我实际上可以看到它的 id
你可以看到我的脚本。
当我连接到数据库时,Thing
table 总是空的(我也在文档中看到了一些关于它的评论)。
现在,我如何告诉 Django 实际填充数据?我正在使用 mysql,并检查完整的日志,我看到 Django 在填充数据(未提交)之前创建了一个 SAVEPOINT
,一旦测试通过,它就会返回到之前的 SAVEPOINT
].
我正在使用:
Django==2.0.1
mysqlclient==1.3.12
pytest==3.3.2
pytest-django==3.1.2
我希望 Django 实际填充 TEST
数据库,使用我的测试信息并在最后删除该数据库,这就是为什么我假设 Django 正在创建一个全新的数据库只是为了测试。
如果您正在使用 django TestCase class,它是 TransactionTestCase class 的子class,数据库将始终重置为原始状态。
https://docs.djangoproject.com/en/2.0/topics/testing/tools/#django.test.TestCase
https://docs.djangoproject.com/en/2.0/topics/testing/tools/#django.test.TransactionTestCase
用于纯函数测试的 django.test.TransactionTestCase
的挂件是标记
pytest.mark.django_db(transaction=True)
来自 pytest-django
。示例(使用 sqlite3
后端):
@pytest.mark.django_db(transaction=True)
def test_model_written_to_db():
obj = MyModel.objects.create(name='foo')
assert obj.id == 1
conn = sqlite3.connect('/tmp/mytestdatabase.sqlite3')
cur = conn.cursor()
cur.execute("SELECT * FROM backend_mymodel")
assert len(cur.fetchall()) == 1
如果您想将标记自动应用于所有测试,您可以使用自定义 pytest_collection_modifyitems
挂钩来实现。在你的 conftest.py
:
import pytest
def pytest_collection_modifyitems(items):
for item in items:
item.add_marker(pytest.mark.django_db(transaction=True))
现在您可以从上面的测试中删除 pytest.mark.django_db
标记,它的行为仍然相同。
但是,自定义挂钩或 pytest
固定装置不适用于 unittest
样式的测试用例子类化 django.test.TestCase
,因此您最好的选择确实是子类化 django.test.TransactionTestCase
, 按照建议 Ghariani Mohamed in