Когда вы пишете код на 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: Напишите тест для функции
Теперь давайте напишем тест для функции сложения. В 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
:
# 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
). - Тест
function test_add_numbers()
будет запускаться один раз для каждого набора входных данных.
Запустите тесты снова с помощью команды pytest, которая выполнит тест четыре раза, один раз для каждого набора входных данных.
Заключение
В этой статье мы научились писать и запускать эффективные модульные тесты в Python с использованием PyTest, чтобы рано находить ошибки и гарантировать, что ваш код работает так, как ожидается.
PyTest облегчает написание и запуск этих тестов, и благодаря своим мощным функциям вы можете справляться с более сложными потребностями в тестировании по мере того, как вы развиваетесь в своем пути с Python.
Source:
https://www.tecmint.com/unit-testing-python-code-with-pytest/