Python · Тестирование с pytest · Экспертный
Тестирование Django-приложений с pytest-django
Тестируйте Django views, модели и формы с помощью встроенных фикстур pytest-django.
Краткое введение в тему и пояснения перед упражнениями (упражнения ниже):
Паттерны тестирования Django на практике
#Справочник pytest-django
#Упражнения:
Проверить что Django-представление возвращает HTTP 200
## pytest.ini
# [pytest]
# DJANGO_SETTINGS_MODULE = myproject.settings
# tests/test_views.py
import pytest
@pytest.mark.django_db
def test_task_list_returns_200(client):
# вызвать GET /tasks/ и проверить статус + структуру
pass
Решение
# pytest.ini
# [pytest]
# DJANGO_SETTINGS_MODULE = myproject.settings
# tests/test_views.py
import pytest
@pytest.mark.django_db
def test_task_list_returns_200(client):
response = client.get('/tasks/')
assert response.status_code == 200
data = response.json()
assert 'results' in data
assert isinstance(data['results'], list)
Проверить сохранение модели и персистентность в базе данных
#import pytest
from myapp.models import Task
@pytest.mark.django_db
def test_default_completed_is_false():
# создать и получить свежий из БД
pass
@pytest.mark.django_db
def test_task_can_be_completed():
# создать, обновить, сохранить, обновить из БД, проверить
pass
Решение
import pytest
from myapp.models import Task
@pytest.mark.django_db
def test_default_completed_is_false():
task = Task.objects.create(title='New task')
task_from_db = Task.objects.get(pk=task.pk)
assert task_from_db.completed is False
@pytest.mark.django_db
def test_task_can_be_completed():
task = Task.objects.create(title='Finish report', completed=False)
task.completed = True
task.save()
task.refresh_from_db()
assert task.completed is True
Проверить аутентифицированное представление с force_login
#import pytest
from myapp.models import Task
@pytest.mark.django_db
def test_my_tasks_redirects_anonymous(client):
pass
@pytest.mark.django_db
def test_my_tasks_returns_only_owners_tasks(client, django_user_model):
pass
Решение
import pytest
from myapp.models import Task
@pytest.mark.django_db
def test_my_tasks_redirects_anonymous(client):
response = client.get('/my-tasks/')
assert response.status_code == 302
@pytest.mark.django_db
def test_my_tasks_returns_only_owners_tasks(client, django_user_model):
alice = django_user_model.objects.create_user(username='alice', password='x')
bob = django_user_model.objects.create_user(username='bob', password='x')
Task.objects.create(title="Alice's task", owner=alice)
Task.objects.create(title="Bob's task", owner=bob)
client.force_login(alice)
response = client.get('/my-tasks/')
assert response.status_code == 200
results = response.json()['results']
assert len(results) == 1
assert results[0]['title'] == "Alice's task"
Переопределить настройку Django для одного теста с фикстурой settings
## tests/test_utils.py
import pytest
from myapp.utils import get_max_tasks
def test_get_max_tasks_with_override(settings):
pass
def test_get_max_tasks_default():
pass
Решение
# tests/test_utils.py
import pytest
from myapp.utils import get_max_tasks
def test_get_max_tasks_with_override(settings):
settings.MAX_TASKS_PER_USER = 3
assert get_max_tasks() == 3
def test_get_max_tasks_default():
assert get_max_tasks() == 10
Проверить функцию представления напрямую с RequestFactory
#import json
import pytest
from myapp.views import task_list, my_tasks
from myapp.models import Task
@pytest.mark.django_db
def test_task_list_with_rf(rf):
pass
@pytest.mark.django_db
def test_my_tasks_with_rf(rf, django_user_model):
pass
Решение
import json
import pytest
from myapp.views import task_list, my_tasks
from myapp.models import Task
@pytest.mark.django_db
def test_task_list_with_rf(rf):
Task.objects.create(title='First')
Task.objects.create(title='Second')
request = rf.get('/tasks/')
response = task_list(request)
assert response.status_code == 200
data = json.loads(response.content)
assert len(data['results']) == 2
@pytest.mark.django_db
def test_my_tasks_with_rf(rf, django_user_model):
user = django_user_model.objects.create_user(username='alice', password='x')
Task.objects.create(title="Alice's task", owner=user)
request = rf.get('/my-tasks/')
request.user = user
response = my_tasks(request)
assert response.status_code == 200
data = json.loads(response.content)
assert len(data['results']) == 1