Введение в тестирование приложений

⏱ 20 мин · 🧩 заданий: 7

Зачем нужны тесты

Вы поправили одну функцию — а сломалась страница в другом конце сайта. Заметите вы это не сразу, а пользователи — сразу. Автоматические тесты — код, который проверяет ваш код. Запустили команду — за секунды узнали, всё ли работает.

Тесты:

  • ловят ошибки до того, как их увидят пользователи;
  • позволяют смело переделывать код (рефакторить);
  • служат документацией: по тесту видно, как должен работать код.

Кстати, у этого учебного сайта тоже есть тесты: они проверяют, что каждое эталонное решение проходит автопроверку.

Первый тест

При создании приложения Django уже положил файл tests.py:

from django.test import TestCase


class SimpleTests(TestCase):
    def test_math(self):
        self.assertEqual(2 + 2, 4)
  • Тесты — методы класса-наследника TestCase.
  • Имя метода обязано начинаться с test.
  • Внутри — проверки self.assert....

Запуск:

python manage.py test           # все тесты проекта
python manage.py test blog      # только приложение blog
python manage.py test blog.tests.PostTests.test_detail  # один тест
Found 1 test(s).
Creating test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

Каждая точка — пройденный тест, F — проваленная проверка, E — ошибка в коде.

Тестовая база данных

Django создаёт отдельную тестовую базу. Каждый тест в TestCase выполняется внутри транзакции, которая в конце откатывается. Тесты не портят ваши данные и не зависят друг от друга.

Тестовый клиент

self.client — «браузер», который умеет отправлять запросы к вашему приложению без запуска сервера:

from django.test import TestCase
from django.urls import reverse


class PageTests(TestCase):
    def test_index(self):
        response = self.client.get(reverse("index"))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Hello, World!")
        self.assertTemplateUsed(response, "hello/index.html")

    def test_post_form(self):
        response = self.client.post("/contacts/", {"email": "a@b.ru", "text": "Привет"})
        self.assertRedirects(response, "/thanks/")

Полезные проверки

Метод Проверяет
assertEqual(a, b) a == b
assertTrue(x) / assertFalse(x) истинность
assertIn(a, b) a in b
assertRaises(Error) код выбрасывает исключение
assertContains(resp, text) статус 200 и текст на странице
assertNotContains(resp, text) текста на странице нет
assertRedirects(resp, url) ответ — перенаправление на url
assertTemplateUsed(resp, name) использован шаблон

Подготовка данных: setUp

class PostTests(TestCase):
    def setUp(self):
        self.user = User.objects.create_user("anna", password="secret123")
        self.post = Post.objects.create(title="Тест", body="Текст", author=self.user)

    def test_detail(self):
        response = self.client.get(self.post.get_absolute_url())
        self.assertContains(response, "Тест")

    def test_login_required(self):
        self.client.login(username="anna", password="secret123")
        response = self.client.get(reverse("blog:post_create"))
        self.assertEqual(response.status_code, 200)

setUp выполняется перед каждым тестом. Для неизменяемых данных быстрее setUpTestData:

    @classmethod
    def setUpTestData(cls):
        cls.user = User.objects.create_user("anna")

Что тестировать

  • Модели: методы и свойства (__str__, get_absolute_url, бизнес-логику).
  • Представления: статус ответа, использованный шаблон, наличие данных, редиректы, права доступа.
  • Формы: что валидные данные проходят, а невалидные — нет.
  • Граничные случаи: пустой список, несуществующий объект (404), анонимный пользователь.

Хорошая привычка — нашли баг, сначала напишите тест, который его воспроизводит, потом исправьте.

Итог

  • Тесты — классы-наследники django.test.TestCase, методы начинаются с test.
  • python manage.py test запускает их на отдельной тестовой базе.
  • self.client отправляет запросы, assert* проверяют результат.
  • setUp / setUpTestData готовят данные.

Практика решено 0 из 7

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Один вариант ответа

Как Django находит тесты при запуске python manage.py test?

Задание 2 Один вариант ответа

С какой базой данных работают тесты Django?

Задание 3 Написать код

Напишите тест test_index_page: тестовый клиент открывает /, а тест проверяет, что статус ответа 200 и на странице есть текст Hello, World!.

Задание 4 Несколько вариантов

Какие методы проверки (assert) есть у django.test.TestCase?

Задание 5 Написать код

Используя reverse, проверьте, что страница поста с pk=999 (маршрут blog:post_detail) отдаёт статус 404. Напишите тело метода test_missing_post.

Задание 6 Ввод ответа

Как называется метод TestCase, который выполняется перед каждым тестом и обычно создаёт тестовые данные?

Задание 7 Практика (выполнить у себя)

Добавьте тест для своей страницы Hello, World и запустите python manage.py test. Вставьте последнюю строку вывода.

Войдите, чтобы отмечать пройденные уроки.