Pytest 使用 django_db 和 rest 框架
Pytest use django_db with rest framework
我正在尝试针对真实 django_db
而不是使用 django rest framework
的测试数据库进行简单测试。
基本测试设置:
import pytest
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIClient
@pytest.mark.django_db
def test_airport_list_real():
client = APIClient()
response = client.get(reverse('query_flight:airports-list'))
assert response.status_code == 200
assert len(response.json()) > 0
运行这次测试我得到:
___________________________ test_airport_list_real ____________________________
@pytest.mark.django_db
def test_airport_list_real():
client = APIClient()
response = client.get(reverse('query_flight:airports-list'))
assert response.status_code == 200
> assert len(response.json()) > 0
E assert 0 > 0
E + where 0 = len([])
E + where [] = functools.partial(<bound method Client._parse_json of <rest_framework.test.APIClient object at 0x000001A0AB793908>>, <Response status_code=200, "application/json">)()
E + where functools.partial(<bound method Client._parse_json of <rest_framework.test.APIClient object at 0x000001A0AB793908>>, <Response status_code=200, "application/json">) = <Response status_code=200, "application/json">.json
query_flight\tests\query_flight\test_api.py:60: AssertionError
当 运行 在 shell 中使用 pipenv run python manage.py shell
时,我得到了预期的结果:
在 [1] 中:从 django.urls 导入反向
In [2]: from rest_framework.test import APIClient
In [3]: client = APIClient()
In [4]: response = client.get(reverse('query_flight:airports-list'))
In [5]: len(response.json())
Out[5]: 100
使用以下包:
pytest-django==3.2.1
pytest [required: >=2.9, installed: 3.5.1]
djangorestframework==3.8.2
django [required: >=1.8, installed: 2.0.5]
有没有办法让pytest
以这种方式访问真实的数据库?
你有几个选择。使用 Django 的 TestClient
或 DRF 的 APIClient
将默认使用您的应用程序的测试数据库和本地版本。要连接到您的实时 API,您可以使用像 Requests 这样的库来执行 HTTP 请求,然后在您的测试中使用这些响应:
import requests
@pytest.mark.django_db
def test_airport_list_real():
response = requests.get('https://yourliveapi.biz')
assert response.status_code == 200
assert len(response.json()) > 0
在该实时数据库上执行独占只读测试时要格外小心。
django_db
标记只负责为标记的测试提供到测试数据库的连接。传递给 pytest-django
的 django 设置完全负责选择测试中使用的数据库 运行.
您可以通过定义 django_db_setup
fixture 覆盖 pytest-django
中的数据库使用。如果您还没有并覆盖数据库配置,请在项目根目录中创建一个 conftest.py
文件:
# conftest.py
import pytest
@pytest.fixture(scope='session')
def django_db_setup():
settings.DATABASES['default'] = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'path/to/dbfile.sqlite3',
}
但是,您不应该在测试中使用真实的数据库。转储当前数据库以获取测试数据的快照 (python manage.py dumpdata > testdata.json
) 并将其加载到空测试数据库中以在测试前填充它 运行:
# conftest.py
import pytest
from django.core.management import call_command
@pytest.fixture(scope='session')
def django_db_setup(django_db_setup, django_db_blocker):
with django_db_blocker.unblock():
call_command('loaddata', 'testdata.json')
现在,您不可能在 运行ning 测试时破坏您的真实数据库;真实数据库中的任何未来更改都不会导致测试失败(例如,当某些数据被删除时)并且您在每个测试中始终具有确定性状态 运行。如果您需要一些额外的测试数据,请将其以 JSON 格式添加到 testdata.json
,您的测试就可以开始了。
我正在尝试针对真实 django_db
而不是使用 django rest framework
的测试数据库进行简单测试。
基本测试设置:
import pytest
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIClient
@pytest.mark.django_db
def test_airport_list_real():
client = APIClient()
response = client.get(reverse('query_flight:airports-list'))
assert response.status_code == 200
assert len(response.json()) > 0
运行这次测试我得到:
___________________________ test_airport_list_real ____________________________
@pytest.mark.django_db
def test_airport_list_real():
client = APIClient()
response = client.get(reverse('query_flight:airports-list'))
assert response.status_code == 200
> assert len(response.json()) > 0
E assert 0 > 0
E + where 0 = len([])
E + where [] = functools.partial(<bound method Client._parse_json of <rest_framework.test.APIClient object at 0x000001A0AB793908>>, <Response status_code=200, "application/json">)()
E + where functools.partial(<bound method Client._parse_json of <rest_framework.test.APIClient object at 0x000001A0AB793908>>, <Response status_code=200, "application/json">) = <Response status_code=200, "application/json">.json
query_flight\tests\query_flight\test_api.py:60: AssertionError
当 运行 在 shell 中使用 pipenv run python manage.py shell
时,我得到了预期的结果:
在 [1] 中:从 django.urls 导入反向
In [2]: from rest_framework.test import APIClient
In [3]: client = APIClient()
In [4]: response = client.get(reverse('query_flight:airports-list'))
In [5]: len(response.json())
Out[5]: 100
使用以下包:
pytest-django==3.2.1
pytest [required: >=2.9, installed: 3.5.1]
djangorestframework==3.8.2
django [required: >=1.8, installed: 2.0.5]
有没有办法让pytest
以这种方式访问真实的数据库?
你有几个选择。使用 Django 的 TestClient
或 DRF 的 APIClient
将默认使用您的应用程序的测试数据库和本地版本。要连接到您的实时 API,您可以使用像 Requests 这样的库来执行 HTTP 请求,然后在您的测试中使用这些响应:
import requests
@pytest.mark.django_db
def test_airport_list_real():
response = requests.get('https://yourliveapi.biz')
assert response.status_code == 200
assert len(response.json()) > 0
在该实时数据库上执行独占只读测试时要格外小心。
django_db
标记只负责为标记的测试提供到测试数据库的连接。传递给 pytest-django
的 django 设置完全负责选择测试中使用的数据库 运行.
您可以通过定义 django_db_setup
fixture 覆盖 pytest-django
中的数据库使用。如果您还没有并覆盖数据库配置,请在项目根目录中创建一个 conftest.py
文件:
# conftest.py
import pytest
@pytest.fixture(scope='session')
def django_db_setup():
settings.DATABASES['default'] = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'path/to/dbfile.sqlite3',
}
但是,您不应该在测试中使用真实的数据库。转储当前数据库以获取测试数据的快照 (python manage.py dumpdata > testdata.json
) 并将其加载到空测试数据库中以在测试前填充它 运行:
# conftest.py
import pytest
from django.core.management import call_command
@pytest.fixture(scope='session')
def django_db_setup(django_db_setup, django_db_blocker):
with django_db_blocker.unblock():
call_command('loaddata', 'testdata.json')
现在,您不可能在 运行ning 测试时破坏您的真实数据库;真实数据库中的任何未来更改都不会导致测试失败(例如,当某些数据被删除时)并且您在每个测试中始终具有确定性状态 运行。如果您需要一些额外的测试数据,请将其以 JSON 格式添加到 testdata.json
,您的测试就可以开始了。