Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Плохие и хорошие практики тестирования Python: Автоматическое тестирование

Как и любой другой код, тесты можно писать по-разному — в том числе очень плохо. Помимо каких-то общих практик и стандартов кодирования у тестов есть свои особенности, о которых надо знать. В этом уроке мы пройдемся по некоторым из них.

Взаимное влияние тестов

Одно из ключевых правил — тесты не должны влиять друг на друга. Это значит, что любой тест выполняется так, как будто других тестов не существует в природе.

Нарушить это правило очень просто. Один тест может создать файл, изменить переменную или записать что-то в базу. Если остальные тесты наткнутся на эти изменения, то они могут работать неверно, например:

  • Упасть там, где не должны падать
  • Успешно пройти там, где не должны проходить

Кроме этого, в такой ситуации вводится неопределенность. Такие тесты могут падать без видимых причин. Например, когда тест запускают изолированно, он работает, а когда вместе с остальными — падает:

user = None

def test_first():
    user = { 'name': 'Vasya' }
    # Тут логика теста

def test_second():
    # Используется пользователь, созданный другим тестом
    # Этот тест зависит от того, как работает предыдущий тест
    # Он не может работать без последовательного запуска обоих тестов
    user["name"] = 'Petya'

Особенно часто такая ситуация возникает в тестах, активно взаимодействующих с внешней средой: базой данных или файловой системой. Тестирование побочных эффектов имеет свои хитрости, которые мы рассматриваем в курсе по продвинутому тестированию.

Условные конструкции в тесте

def test_something():
    if (something):
        # Выполняем код одним способом
        # Проверка может быть тут
    else:
        # Выполняем код другим способом
        # Проверка может быть тут
    # Проверка может быть тут

Любое ветвление в тестах — это фактически несколько тестов в одном. Ветвления порождают код, который сам нуждается в тестировании. Так происходит, потому что порядок выполнения становится не очевидным — его можно случайно нарушить. Лучше создать независимые тесты для каждой ветки.

Тест вне тестов

Задача фикстур — готовить данные и среду для тестирования, а задача тестовых функций — проводить проверки и вызывать код для тестирования. Но иногда разработчики переусердствуют:

# Тестируем функцию sum()

import pytest

@pytest.fixture
def result():
    # Вызывается тестируемый код
    return sum([5, 9])

def test_sum(result):
    assert result == 14

В этом примере тестируемый код вызывается в функции result(). Такой подход усложняет анализ тестов, потому что переворачивает все с ног на голову.

Слишком сильная детализация

Некоторые программисты стремятся максимально разносить код по файлам, модулям и функциям. То же самое наблюдается и в тестах. Вместо одного теста со всеми необходимыми проверками, они создают пять тестов, в каждом из которых ровно одна проверка:

def test_create_user():
    user = { 'name': 'Mark', 'age': 28 }
    # Код, добавляющий пользователя в базу данных
    assert user['age'] == 28
def test_create_user():
    user = { 'name': 'Mark', 'age': 28 }
    # Код, добавляющий пользователя в базу данных
    assert user['name'] == 'Mark'

У такого разделения есть одно последствие — кода станет больше, а значит сложнее будет провести рефакторинг в будущем.

Код с тестами писать дольше, чем код без тестов

Это очень интересный вопрос, по которому можно понять, насколько хорошо программист умеет писать тесты.

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

  • Тесты помогают раньше выявить неудачные решения и поэтому влияют на дизайн кода
  • Тесты упрощают подготовку входных данных — ее нужно сделать всего один раз
  • Тесты упрощают проверку результата работы кода, ведь сами проверяют все, в том числе и пограничные случаи
  • Регулярные тесты упрощают и ускоряют рефакторинг, потому что с ними не приходится проверять части кода вручную
  • Тесты улучшают атмосферу в команде, потому что снижают уровень стресса

Дополнительные материалы

  1. Начинаем писать тесты правильно

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Python-разработчик
Профессия
с нуля
Разработка веб-приложений на Django
2 февраля 10 месяцев

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»