简体   繁体   English

如何在使用pytest-django的测试之间将数据持久保存到数据库?

[英]How to persist data to DB between tests with pytest-django?

How can I persist data to DB when using pytest/pytest-django in a test-run of a Django application? 在Django应用程序的测试运行中使用pytest / pytest-django时,如何将数据持久化到数据库?

I run pytest with py.test --nomigrations --reuse-db -s and the Postgres DB test_<configued_db_name> is created as expected, however nothing seems to be persisted to DB between tests and at the end of the test run the DB is empty. 我使用py.test --nomigrations --reuse-db -s运行pytest py.test --nomigrations --reuse-db -s预期创建了Postgres DB test_<configued_db_name> ,但是在测试之间似乎没有任何持久性,并且在测试结束时运行DB是空的。

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

The first test passes, the second does not making me wonder if anything is persisted to DB at all. 第一个测试通过了,第二个没有让我怀疑是否任何东西都可以持久保存到数据库中。 According to the pystest-django documentation @pytest.mark.django_db(transaction=False) will not rollback whatever has been affected by the decorated test. 根据pystest-django文档, @pytest.mark.django_db(transaction=False)不会回滚任何受修饰测试影响的内容。

Thank you, 谢谢,

/David /大卫

Another way of prefilling the database with data for each function is like that: 用每个函数的数据预填充数据库的另一种方式是:

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'}

The good thing about this method is that the setup function is only called once: 关于此方法的好处是,setup函数仅被调用一次:

plugins: django-3.1.2
collected 2 items

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

The bad thing is that 1.38 seconds is a bit too much for such a simple test. 不好的是,对于这样一个简单的测试,1.38秒实在太多了。 --reuse-db is a faster way to do it. --reuse-db是一种更快的方法。

I have solved this problem -- prefill the DB for every function -- by defining a fixture with scope function (ie model and session will not work). 我已经解决了这个问题-为每个功能预填充数据库-通过定义具有作用域function的夹具(即modelsession将不起作用)。

Here is the code for testing the views in Django. 这是用于在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"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM