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