7

我正在设置一个非常简单的 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表总是空的(我还在文档中看到了一些关于它的评论)。

现在,我如何告诉 Django 实际填充数据?我正在使用 mysql,并检查完整的日志,我看到 DjangoSAVEPOINT在填充数据(未提交)之前创建了一个,一旦测试通过,它就会回到之前的SAVEPOINT.

我在用:

Django==2.0.1
mysqlclient==1.3.12
pytest==3.3.2
pytest-django==3.1.2

我希望 DjangoTEST使用来自我的测试的信息来实际填充数据库,最后删除该数据库,这就是为什么我假设 Django 正在创建一个全新的数据库只是为了测试。

4

2 回答 2

4

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-style testcases subclassing django.test.TestCase,因此您最好的选择确实是 subclassing django.test.TransactionTestCase,正如Ghariani Mohamed他的回答中所建议的那样。

于 2018-01-30T23:34:54.740 回答
2

如果您使用的是 django TestCase 类,该类是 TransactionTestCase 类的子类,则数据库将始终重置为原始状态。

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

于 2018-01-29T23:53:18.037 回答