强制Django测试将模型写入数据库

eLR*_*uLL 6 python mysql django pytest pytest-django

我正在建立一个非常简单的Django项目,并且测试非常简单:

def test_name(self):
    t = Thing.objects.create(name='a')
    print(t.id)
    import time
    time.sleep(30)
    self.assertEqual('a', t.name)
Run Code Online (Sandbox Code Playgroud)

当然测试通过,但是数据库(TEST数据库)没有填充我的Thing模型信息,即使我可以看到它,id因为你可以看到我的脚本.

当我连接到数据库时,Thing表总是空的(我在文档中也看到了一些关于它的评论).

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

我在用:

Django==2.0.1
mysqlclient==1.3.12
pytest==3.3.2
pytest-django==3.1.2
Run Code Online (Sandbox Code Playgroud)

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

hoe*_*ing 4

纯功能测试的吊坠django.test.TransactionTestCase是标记

pytest.mark.django_db(transaction=True)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

如果您想将标记自动应用于所有测试,可以使用自定义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))
Run Code Online (Sandbox Code Playgroud)

现在您可以pytest.mark.django_db从上述测试中删除标记,它的行为仍然相同。

然而,自定义挂钩或pytest固定装置不适用于unittest-style 测试用例子类化django.test.TestCase,因此最好的选择确实是子类化django.test.TransactionTestCase,正如Ghariani Mohamed他的回答中所建议的那样。