Поиск по сайту:

Как писать и запускать модульные тесты на Python с помощью PyTest


Когда вы пишете код на Python, важно убедиться, что ваш код работает должным образом. Один из лучших способов сделать это — использовать модульные тесты, которые помогут вам проверить, правильно ли работают небольшие части (или блоки) вашего кода.

В этой статье мы узнаем, как писать и проводить эффективные модульные тесты на Python с помощью PyTest, одного из самых популярных фреймворков для тестирования Python.

Что такое модульные тесты?

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

Модульные тесты могут быть написаны для различных частей вашего кода, таких как функции, методы и даже классы. С помощью модульных тестов можно протестировать код, не запуская всю программу.

Зачем использовать PyTest?

PyTest — это популярная среда тестирования для Python, которая упрощает написание и проведение тестов.

Он прост в использовании и имеет множество полезных функций, таких как:

  • Он позволяет писать простые и понятные тест-кейсы.
  • Он предоставляет расширенные функции, такие как фикстуры, параметризованные тесты и плагины.
  • Он хорошо работает с другими инструментами тестирования и библиотеками.
  • Он генерирует легко читаемые результаты тестов и отчеты.

Настройка PyTest в Linux

Прежде чем мы начнем писать тесты, нам нужно установить PyTest. Если у вас не установлен PyTest, вы можете установить его с помощью менеджера пакетов Python под названием pip.

pip install pytest

Как только PyTest будет установлен, вы будете готовы приступить к написанию тестов!

Написание вашего первого теста с помощью PyTest

Давайте начнем с написания простой функции, а затем напишем тест для нее.

Шаг 1: Напишите простую функцию

Во-первых, давайте создадим функцию Python, которую мы хотим протестировать. Допустим, у нас есть функция, которая складывает два числа:

# add.py
def add(a, b):
    return a + b

Это простая функция, которая принимает два числа a и b, складывает их вместе и возвращает результат.

Шаг 2: Напишите тест для функции

Теперь давайте напишем тест для функции add. В PyTest тесты записываются в отдельных файлах, обычно называемых test_*.py чтобы упростить идентификацию тестовых файлов.

Создайте новый файл с именем test_add.py и напишите следующий тестовый код:

# test_add.py
from add import add

def test_add_numbers():
    assert add(2, 3) == 5
    assert add(-1, 1) == 0
    assert add(0, 0) == 0

Пояснение к приведенному выше коду:

  • Импортируем функцию add из файла add.py.
  • Мы определяем тестовую функцию с именем test_add_numbers(). В PyTest тестовая функция должна начинаться со слова test_.
  • Внутри тестовой функции мы используем оператор assert, чтобы проверить, соответствует ли результат вызова функции add ожидаемому значению. Если условие в операторе assert равно True, тест проходит, в противном случае он завершается ошибкой.

Шаг 3: Запустите тест

Чтобы запустить тест, откройте терминал и перейдите в каталог, где находится файл test_add.py, а затем выполните следующую команду:

pytest

PyTest автоматически найдет все тестовые файлы (те, которые начинаются с test_) и запустит тесты внутри них. Если все работает правильно, вы должны увидеть такой вывод:

Точка (.) указывает на то, что тест пройден. Если возникали какие-либо проблемы, PyTest выдавал сообщение об ошибке.

Написание более сложных тестов

Теперь, когда мы знаем, как написать и запустить базовый тест, давайте рассмотрим некоторые более продвинутые функции PyTest.

Тестирование на наличие ожидаемых исключений

Иногда требуется проверить, создает ли ваш код правильные исключения, когда что-то идет не так. Вы можете сделать это с помощью функции pytest.raises().

Допустим, мы хотим протестировать функцию, которая делит два числа. Мы хотим вызвать исключение, если второе число равно нулю (чтобы избежать деления на ноль ошибок).

Вот функция деления:

# divide.py
def divide(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b

Теперь давайте напишем тест для этой функции, который проверяет, возникает ли ошибка ValueError, когда мы пытаемся разделить на ноль:

# test_divide.py
from divide import divide
import pytest

def test_divide_numbers():
    assert divide(10, 2) == 5
    assert divide(-10, 2) == -5
    assert divide(10, -2) == -5

def test_divide_by_zero():
    with pytest.raises(ValueError):
        divide(10, 0)

Объяснение кода:

  • Мы добавили новую тестовую функцию под названием test_divide_by_zero().
  • Внутри этой функции мы используем pytest.raises(ValueError) для проверки, возникает ли ValueError при вызове функции деления с нулем в качестве второго аргумента.

Запустите тесты еще раз с помощью команды pytest. Если все работает правильно, вы должны увидеть этот вывод:

Использование фикстур для настройки и очистки

В некоторых случаях может потребоваться настроить определенные условия перед запуском тестов или выполнить очистку после их завершения. PyTest предоставляет приспособления для решения этой проблемы.

Приспособление — это функция, которую можно использовать для настройки или демонтажа условий для испытаний. Фикстуры часто используются для создания объектов или подключения к базам данных, которые необходимы для тестов.

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

# test_file_operations.py
import pytest
import os

@pytest.fixture
def temporary_directory():
    temp_dir = "temp_dir"
    os.mkdir(temp_dir)
    yield temp_dir  # This is where the test will run
    os.rmdir(temp_dir)  # Cleanup after the test

def test_create_file(temporary_directory):
    file_path = os.path.join(temporary_directory, "test_file.txt")
    with open(file_path, "w") as f:
        f.write("Hello, world!")
    
    assert os.path.exists(file_path)

Объяснение кода:

  • Мы определяем фикстуру с именем temporary_directory, которая создает временный каталог перед тестом и удаляет его впоследствии.
  • Тестовая функция test_create_file() использует эту фикстуру для создания файла во временном каталоге и проверяет, существует ли файл.

Запустите тесты еще раз с помощью команды pytest. PyTest автоматически обнаружит и использовать приспособление.

Параметризуйте свои тесты с помощью pytest

Иногда требуется выполнить один и тот же тест с разными входными данными. PyTest позволяет легко сделать это с помощью параметризации.

Допустим, мы хотим протестировать нашу функцию add с несколькими парами чисел. Вместо того, чтобы писать отдельные тестовые функции для каждой пары, мы можем использовать pytest.mark.parametrize для запуска одного и того же теста с разными входными данными.

# test_add.py
import pytest
from add import add

@pytest.mark.parametrize("a, b, expected", [
    (2, 3, 5),
    (-1, 1, 0),
    (0, 0, 0),
    (100, 200, 300)
])
def test_add_numbers(a, b, expected):
    assert add(a, b) == expected

Объяснение кода:

  • Мы используем декоратор pytest.mark.parametrize для определения нескольких наборов входных данных (a, b и expected).
  • Тестовая функция test_add_numbers() будет выполняться один раз для каждого набора входных параметров.

Запустите тесты снова с помощью команды pytest, которая запустит тест четыре раза, по одному разу для каждого набора входных данных.

Заключение

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

PyTest упрощает написание и выполнение этих тестов, а благодаря своим мощным функциям вы можете справляться с более сложными задачами тестирования по мере вашего роста в путешествии по Python.

Статьи по данной тематике: