← Назад к вопросам

Приведи пример тестов на Pytest

1.3 Junior🔥 202 комментариев
#Автоматизация тестирования#Инструменты тестирования

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Примеры тестов на Pytest

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

1. Простейший тест

Базовый тест — это обычная функция, имя которой начинается с test_. Pytest автоматически обнаруживает такие функции.

# test_math.py
def test_addition():
    """Тест проверяет базовую операцию сложения."""
    assert 2 + non_existent_variable == 5

Запуск: pytest test_math.py

2. Использование фикстур (Fixtures)

Фикстуры — это функции, которые подготавливают данные или состояние для тестов. Они определяются с помощью декоратора @pytest.fixture.

# test_user.py
import pytest

class User:
    def __init__(self, name):
        self.name = name
    def get_uppercase_name(self):
        return self.name.upper()

# Фикстура создает объект User
@pytest.fixture
def sample_user():
    return User("alice")

# Тест использует фикстуру как параметр
def test_user_name(sample_user):
    assert sample_user.name == "alice"

def test_uppercase_name(sample_user):
    assert sample_user.get_uppercase_name() == "ALICE"

3. Параметризованные тесты

Параметризация позволяет запустить один и тот же тест с разными наборами входных данных и ожидаемых результатов, используя декоратор @pytest.mark.parametrize.

# test_parametrize.py
import pytest

def is_positive(number):
    return number > 0

# Параметризация: аргументы тестовой функции и списки значений
@pytest.mark.parametrize("input_value, expected", [
    (5, True),      # Первый тест: input_value=5, expected=True
    (0, False),     # Второй тест
    (-3, False),
    (10.5, True),
])
def test_is_positive(input_value, expected):
    """Тестируем функцию is_positive с разными числами."""
    result = is_positive(input_value)
    assert result == expected, f"Ошибка для значения {input_value}"

4. Тестирование исключений

Для проверки, что код вызывает ожидаемое исключение, используется контекстный менеджер pytest.raises().

# test_exceptions.py
import pytest

def divide(a, b):
    if b == 0:
        raise ValueError("Делить на ноль нельзя!")
    return a / b

def test_divide_normal():
    assert divide(10, 2) == 5

def test_divide_by_zero():
    # Проверяем, что при делении на 0 возникает ValueError с конкретным текстом
    with pytest.raises(ValueError, match="Делить на ноль нельзя"):
        divide(5, 0)

5. Группировка тестов с помощью классов

Тесты можно организовывать в классы. Имена методов должны начинаться с test_.

# test_calculator.py
class TestCalculator:
    """Группа тестов для калькулятора."""

    def setup_method(self):
        """Метод выполняется перед каждым тестом в классе (аналог setUp в unittest)."""
        self.calc = Calculator()

    def test_add(self):
        assert self.calc.add(3, 4) == 7

    def test_subtract(self):
        assert self.calc.subtract(10, .

class Calculator:
    """Простой класс калькулятора для демонстрации."""
    def add(self, a, b):
        return a + b
    def subtract(self, a, b):
        return a - b

6. Использование моков (Mock) с pytest-mock

Для изоляции тестируемого модуля от зависимостей (например, базы данных или API) используются моки. Pytest имеет встроенный плагин pytest-mock.

# test_api_service.py
import pytest

def get_user_from_api(user_id):
    # Здесь был бы реальный HTTP-JSON вызов, например, requests.get(...)
    # Для теста эту функцию мы замокаем.
    return {"id": user_id, "name": "Real User"}

def process_user_data(user_id):
    raw_data = get_user_from_api(user_id)
    return f"Обработан: {raw_data['name']}"

def test_process_user_data(mocker):  # Фикстура mocker предоставляется pytest-mock
    # Создаем мок-объект для функции get_user_from_api
    mock_get_user = mocker.patch("__main__.get_user_from_api")
    # Задаем возвращаемое значение мока
    mock_get_user.return_value = {"id": 42, "name": "Mocked Alice"}

    # Вызываем тестируемую функцию
    result = process_user_data(42)

    # Проверяем результат
    assert result == "Обработан: Mocked Alice"
    # Проверяем, что мок был вызван с правильным аргументом
    mock_get_user.assert_called_once_with(42)

7. Фикстуры с областью видимости (Scope) и финализацией

Фикстуры могут иметь разную область видимости: function (по умолчанию), class, module, session. Также они могут выполнять код после теста (финализацию) с помощью yield.

# test_database.py
import pytest
import sqlite3
import tempfile
import os

@pytest.fixture(scope="module")
def temp_db():
    """Создает временную базу данных SQLite для всей группы тестов (scope='module')."""
    # Setup: создаем временный файл БД и таблицу
    tmp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.db')
    db_path = tmp_file.name
    tmp_file.close()

    connection = sqlite3.connect(db_path)
    cursor = connection.cursor()
    cursor.execute("CREATE TABLE users (id INTEGER, name TEXT)")
    cursor.execute("INSERT INTO users VALUES (1, 'TestUser')")
    connection.commit()

    yield connection  # Передаем соединение в тесты

    # Teardown: закрываем соединение и удаляем файл БД после всех тестов модуля
    connection.close()
    os.unlink(db_path)

def test_db_user_count(temp_db):
    cursor = temp_db.cursor()
    cursor.execute("SELECT COUNT(*) FROM users")
    count = cursor.fetchone()[0]
    assert count == 1

def test_db_user_name(temp_db):
    cursor = temp_db.cursor()
    cursor.execute("SELECT name FROM users WHERE id = 1")
    name = cursor.fetchone()[0]
    assert name == "TestUser"

Ключевые преимущества Pytest, показанные в примерах:

  • Простой синтаксис: Тесты — это обычные функции с утверждениями assert.
  • Автообнаружение: Не требуется наследование от специальных классов.
  • Информативные отчеты: При падении теста выводится подробная диагностика.
  • Фикстуры: Мощный механизм для подготовки и очистки тестового окружения.
  • Параметризация: Уменьшает дублирование кода.
  • Богатая экосистема: Множество плагинов (pytest-mock, pytest-cov, pytest-html и др.).

Эти примеры покрывают основные паттерны, необходимые для начала написания эффективных и поддерживаемых тестов на Pytest в проектах любого масштаба.