Какие инструменты для тестирования в Python вы знаете и как написать простой тест с помощью pytest

Ответ

В Python существует несколько фреймворков для тестирования, но основными являются:

  • unittest: Входит в стандартную библиотеку Python. Основан на xUnit, требует создания классов для тестов и использования специальных assert методов (например, self.assertEqual()).
  • pytest: Де-факто стандарт в сообществе. Отличается простым синтаксисом (использует стандартный assert), мощной системой фикстур, плагинами и подробными отчетами об ошибках.

Написание теста с pytest

pytest автоматически обнаруживает файлы test_*.py или *_test.py и функции test_* в них.

1. Код для тестирования (например, calculator.py):

# calculator.py

class CalculationError(Exception):
    pass

def add(a: int, b: int) -> int:
    if not isinstance(a, int) or not isinstance(b, int):
        raise TypeError("Оба аргумента должны быть целыми числами")
    return a + b

2. Файл с тестами (test_calculator.py):

# test_calculator.py
import pytest
from calculator import add, CalculationError

# Простой тест на корректное сложение
def test_add_positive_numbers():
    assert add(2, 3) == 5

# Параметризованный тест для проверки нескольких случаев
@pytest.mark.parametrize("a, b, expected", [
    (1, 2, 3),      # Положительные числа
    (-1, -1, -2),   # Отрицательные числа
    (-5, 5, 0),     # Смешанные числа
    (0, 0, 0)       # Нули
])
def test_add_various_cases(a, b, expected):
    assert add(a, b) == expected

# Тест на проверку вызова исключения
def test_add_raises_type_error_for_strings():
    with pytest.raises(TypeError):
        add("a", "b")

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

Ответ 18+ 🔞

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

Вот смотри, в Питоне для проверки, что твой код не превратился в тыкву, есть пара основных инструментов. Не то чтобы их было дохуища, но два главных — это unittest и pytest.

  • unittest — это как старый, проверенный дедовский метод. Он уже встроен в сам Питон, из коробки. Но, блядь, там надо писать классы, наследоваться от какого-то TestCase и юзать ихние методы вроде self.assertEqual(). Ну такое, знаешь, олдскул. Работает, но иногда ощущение, что ты не тест пишешь, а бумажку для бухгалтерии заполняешь.
  • pytest — а вот это уже, сука, песня! Это сейчас де-факто стандарт. Всё просто, как три копейки: пишешь обычный assert, и он сам всё понимает. Плюс у него фикстуры — это вообще магия, плагинов дохуя, а отчёты об ошибках такие подробные, что можно понять, где именно ты, мудак, накосячил.

Как это выглядит на практике, ёпта?

Допустим, у нас есть файлик с какой-то логикой. Назовём его calculator.py, чтобы было понятно, о чём речь.

# calculator.py

class CalculationError(Exception):
    pass

def add(a: int, b: int) -> int:
    if not isinstance(a, int) or not isinstance(b, int):
        raise TypeError("Оба аргумента должны быть целыми числами")
    return a + b

Всё, функция сложения есть. Теперь надо её протестировать, чтобы не оказалось, что 2 + 3 вдруг равно "банан".

Создаём рядом файл test_calculator.py. pytest — хитрая жопа, он сам ищет файлы, которые начинаются на test_ или заканчиваются на _test.py, и функции внутри них с префиксом test_.

# test_calculator.py
import pytest
from calculator import add, CalculationError

# Самый примитивный тест: сложили два плюса, получили пятерку.
def test_add_positive_numbers():
    assert add(2, 3) == 5

# А вот это уже круто — параметризованный тест.
# Одной функцией проверяем кучу разных случаев. Экономия времени, блядь!
@pytest.mark.parametrize("a, b, expected", [
    (1, 2, 3),      # Обычные положительные
    (-1, -1, -2),   # Оба отрицательные
    (-5, 5, 0),     # Плюс и минус
    (0, 0, 0)       # Нули
])
def test_add_various_cases(a, b, expected):
    assert add(a, b) == expected

# А это тест на то, что функция правильно матерится, если ей дать не то.
# Проверяем, вылетает ли нужное исключение, когда пытаемся сложить строки.
def test_add_raises_type_error_for_strings():
    with pytest.raises(TypeError):
        add("a", "b")

И всё, ёпта! Запускаешь в терминале просто команду pytest, и он сам всё прогонит. Выдаст красивый отчёт: что прошло, что упало, и почему. Если всё зелёное — можно спать спокойно. Если красное — ну, значит, пора думать, бошка, где ты накосячил.