6

在 Django 应用程序的测试运行中使用 pytest/pytest-django 时,如何将数据保存到数据库?

我运行 pytest并按预期创建py.test --nomigrations --reuse-db -s了 Postgres 数据库test_<configued_db_name>,但是在测试之间似乎没有任何东西被持久化到数据库中,并且在测试运行结束时数据库为空。

import pytest
from django.contrib.auth.models import User


@pytest.mark.django_db(transaction=False)
def test_insert_user():
    user = User.objects.create_user(username="test_user", email="test_user@test.com", password="test")
    users = User.objects.all()
    assert len(users) > 0

@pytest.mark.django_db(transaction=False)
def test_check_user():
    users = User.objects.all()
    assert len(users) > 0

第一个测试通过,第二个测试并没有让我怀疑是否有任何东西被持久化到数据库中。根据 pystest-django 文档@pytest.mark.django_db(transaction=False)将不会回滚任何受装饰测试影响的内容。

谢谢,

/大卫

4

2 回答 2

5

用每个函数的数据预填充数据库的另一种方法是:

import pytest

from django.contrib.auth.models import User

@pytest.fixture(scope='module')
def django_db_setup(django_db_setup, django_db_blocker):
    print('setup')
    with django_db_blocker.unblock():
        User.objects.create(username='a')
        assert set(u.username for u in User.objects.all()) == {'a'}

@pytest.mark.django_db
def test1():
    print('test1')
    User.objects.create(username='b')
    assert set(u.username for u in User.objects.all()) == {'a', 'b'}

@pytest.mark.django_db
def test2():
    print('test2')
    User.objects.create(username='c')
    assert set(u.username for u in User.objects.all()) == {'a', 'c'}

这个方法的好处是 setup 函数只被调用一次:

plugins: django-3.1.2
collected 2 items

mytest.py setup
test1
.test2
.
=================== 2 passed in 1.38 seconds ====================

不好的是 1.38 秒对于这样一个简单的测试来说有点太多了。--reuse-db是一种更快的方法。

于 2017-05-11T12:08:54.830 回答
0

我已经解决了这个问题——为每个函数预填充数据库——通过定义一个具有范围的夹具function(即modelsession将不起作用)。

这是在 Django 中测试视图的代码。

# This is used to fill the database more easily
from mixer.backend.django import mixer

import pytest

from django.test import RequestFactory

from inventory import views
from inventory import services

pytestmark = pytest.mark.django_db

@pytest.fixture(scope="function")
def fill_db():
    """ Just filling the DB with my data """
    for elem in services.Search().get_lookup_data():
        mixer.blend('inventory.Enumeration', **elem)

def test_grid_anonymous(fill_db):
    request = RequestFactory().get('/grid/')
    response = views.items_grid(request)
    assert response.status_code == 200, \
        "Should be callable by anyone"

def test_list_anonymous(fill_db):
    request = RequestFactory().get('/')
    response = views.items_list(request)
    assert response.status_code == 200, \
        "Should be callable by anyone"
于 2017-03-02T18:44:18.337 回答