pytest 和失败:不允许数据库访问,使用“django_db”标记,或“db”或“transactional_db”固定装置来启用它

问题描述 投票:0回答:4

在从 shell 调用 pytest 期间,我得到以下输出,因为我的测试存储在 apps.business.metrics.tools.tests.py 中,并且在导入模块期间

apps/business/metrics/widgets/employees/utilization.py

在模块调用期间实时调用 SQL。这是由

完成的

get_metric_columns('EmployeeUtilization', shapers=SHAPERS)

和 pytest 投诉:

➜ pytest
=========================================================================== test session starts ===========================================================================
platform linux -- Python 3.6.8, pytest-4.0.0, py-1.7.0, pluggy-0.8.0
Django settings: config.settings.local (from ini file)
rootdir: /home/dmitry/Projects/analytics/backend, inifile: pytest.ini
plugins: django-3.4.7, pylama-7.6.6, django-test-plus-1.1.1, celery-4.2.1
collected 60 items / 1 errors                                                                                                                                             

================================================================================= ERRORS ==================================================================================
__________________________________________________________ ERROR collecting apps/business/metrics/tools.tests.py __________________________________________________________
../../../.pyenv/versions/3.6.8/envs/cam/lib/python3.6/site-packages/py/_path/local.py:668: in pyimport
    __import__(modname)
apps/business/metrics/__init__.py:3: in <module>
    from .widgets import *  # noqa
apps/business/metrics/widgets/__init__.py:1: in <module>
    from . import help  # noqa
apps/business/metrics/widgets/help.py:1: in <module>
    from .employees.utilization import EmployeeSwarmUtilization
apps/business/metrics/widgets/employees/utilization.py:19: in <module>
    get_metric_columns('EmployeeUtilization', shapers=SHAPERS)
apps/business/metrics/tools.py:132: in get_metric_columns
    m = get_metric(metric, period=p, shapers=shapers)
apps/business/metrics/data/__init__.py:23: in get_metric
    return metrics[name](*args, **kwargs)
apps/business/metrics/data/abstract.py:441: in __init__
    self._to_dataframe(self.sql or self._ingest())
apps/business/metrics/data/abstract.py:472: in _to_dataframe
    source, connection, params=query_params, index_col=self.index
../../../.pyenv/versions/3.6.8/envs/cam/lib/python3.6/site-packages/pandas/io/sql.py:381: in read_sql
    chunksize=chunksize)
../../../.pyenv/versions/3.6.8/envs/cam/lib/python3.6/site-packages/pandas/io/sql.py:1413: in read_query
    cursor = self.execute(*args)
../../../.pyenv/versions/3.6.8/envs/cam/lib/python3.6/site-packages/pandas/io/sql.py:1373: in execute
    cur = self.con.cursor()
../../../.pyenv/versions/3.6.8/envs/cam/lib/python3.6/site-packages/django/db/backends/base/base.py:255: in cursor
    return self._cursor()
../../../.pyenv/versions/3.6.8/envs/cam/lib/python3.6/site-packages/django/db/backends/base/base.py:232: in _cursor
    self.ensure_connection()
E   Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
========================================================================= 1 error in 2.43 seconds =========================================================================

有没有办法用 pytest 处理这种情况?

我知道我可以将 get_metric_columns('EmployeeUtilization', shapers=SHAPERS) 转换为部分函数并更改实现,但是还有其他方法吗?

python-3.x pytest django-testing pytest-django
4个回答
41
投票

解决方案:

import pytest


@pytest.mark.django_db
class TestExample:
    def test_one():
        ...

假设您已在测试文件中创建了一个

TestExample
类,并且应使用
@pytest.mark.django_db
进行装饰。应该可以解决你的问题。


5
投票

解决此问题的另一种方法是在测试类中继承 Django

TestCase

from django.test import TestCase


class TestExampleTestCase(TestCase):
    def test_one():
        ...

确保导入

django.test.TestCase
而不是
unittest.TestCase

接受的答案也应该有效,但这将为您提供 Django 测试框架提供的额外工具,并且是根据关于测试的 Django 官方文档编写测试的标准方法。


1
投票

如果您有标记但仍然收到错误,请确保您没有从测试函数外部访问数据库。

例如:

@pytest.mark.django_db
class TestEndpoint:
    user = User.objects.create()    # Accessing the database outside a test function will raise the error

    def test_endpoint(self):
        pass

相反,将访问数据库的任何代码移至测试函数中。如果您想重复使用它,我建议将其设为固定装置。


0
投票

如错误所示,您应该使用 @pytest.mark.django_dbdbtransactional_db

@pytest.mark.django_db
对于
test_1()

import pytest

from django.contrib.auth.models import User

@pytest.mark.django_db # Here
def test_1():
    count = User.objects.all().count()    
    assert count == 0

@pytest.mark.django_db
对于
test_1()
@pytest.fixture:

import pytest

from django.contrib.auth.models import User

@pytest.fixture
def fixture_1():
    count = User.objects.all().count() 
    return count

@pytest.mark.django_db
def test_1(fixture_1):
    count = fixture_1
    assert count == 0

db
fixture_1()
@pytest.fixture
:

import pytest

from django.contrib.auth.models import User

@pytest.fixture
def fixture_1(db):
    count = User.objects.all().count() 
    return count

def test_1(fixture_1):
    count = fixture_1
    assert count == 0

transactional_db
fixture_1()
@pytest.fixture
:

import pytest

from django.contrib.auth.models import User

@pytest.fixture
def fixture_1(transactional_db):
    count = User.objects.all().count() 
    return count

def test_1(fixture_1):
    count = fixture_1
    assert count == 0
© www.soinside.com 2019 - 2024. All rights reserved.