Чем удобен pytest

Обзор pytest: чем он удобнее unittest — простой assert, меньше шаблона.

pytest — популярный сторонний фреймворк тестирования. Его не нужно знать, чтобы тестировать на Python, но он делает тесты короче и читабельнее.

Важно: pytest — внешняя библиотека

В отличие от unittest, pytest не входит в стандартную библиотеку — его ставят через pip. Поэтому код в этом разделе показан как разметка для чтения (его нельзя запустить в браузере), а команды установки — как терминальные.

pip install pytest
pytest --version

Тест на pytest — это просто функция

Главное отличие: не нужны ни класс, ни наследование от TestCase, ни методы assert*. Тест — обычная функция test_*, а проверка — встроенный оператор assert.

# файл test_calc.py
def add(a, b):
    return a + b

def test_add_positive():
    assert add(2, 3) == 5

def test_add_negative():
    assert add(-1, -1) == -2

Сравните с unittest, где то же самое требует класса и self.assertEqual:

# то же самое на unittest — заметно многословнее
import unittest

class TestAdd(unittest.TestCase):
    def test_add_positive(self):
        self.assertEqual(add(2, 3), 5)

    def test_add_negative(self):
        self.assertEqual(add(-1, -1), -2)

Умный assert: понятная диагностика бесплатно

Может показаться, что голый assert даст плохое сообщение об ошибке. Но pytest переписывает assert и показывает значения обеих сторон не хуже, чем assertEqual. Например, при падении assert add(2, 2) == 5 вы увидите примерно такое:

    def test_add():
>       assert add(2, 2) == 5
E       assert 4 == 5
E        +  where 4 = add(2, 2)

То есть удобство assertEqual вы получаете, оставаясь с привычным assert. Не нужно помнить десятки имён assert-методов — везде один assert с любым выражением.

Запуск pytest

pytest сам находит файлы test_*.py и функции test_* — отдельная команда discover не нужна:

# запустить все тесты в проекте
pytest

# подробный вывод
pytest -v

# только один файл / один тест
pytest test_calc.py
pytest test_calc.py::test_add_positive

Что упрощает pytest по сравнению с unittest

Аспектunittestpytest
структура тестакласс + методыпросто функция
проверкаself.assertEqual(...)assert ...
имена проверокмного assert*один assert
установкавстроенpip install

Совместимость

Приятный факт: pytest умеет запускать и тесты, написанные на unittest. Можно начать с unittest (он встроен), а позже добавить pytest как раннер — старые тесты продолжат работать. Поэтому знание unittest не пропадёт.

Почему pytest стал стандартом де-факто

В современных Python-проектах pytest встречается чаще, чем «голый» unittest, и причина не только в коротком синтаксисе. Вокруг pytest выросла огромная экосистема плагинов: покрытие, моки, параллельный запуск, тестирование asyncio, интеграции с Django и Flask. Добавить любой из них — одна команда pip install, без правки кода тестов. Плюс удобный вывод: при падении pytest показывает локальные переменные и наглядно подсвечивает, что именно не совпало. Всё это экономит время на отладке тестов.

Тем не менее знать unittest по-прежнему важно. Он встроен, поэтому работает в любом окружении без установки — в Docker-образе «на минималках», в стандартной поставке Python, в обучающей песочнице вроде этой. И главное: unittest учит фундаментальным понятиям (TestCase, фикстуры, assert-методы), которые лежат и в основе pytest. Освоив фундамент, вы легко добавите поверх удобства pytest.

Итог

  • pytest — сторонний фреймворк, ставится через pip install pytest.
  • Тест — обычная функция test_* с оператором assert, без классов.
  • pytest переписывает assert и даёт понятную диагностику без assert*-методов.
  • pytest умеет запускать и существующие unittest-тесты.
Проверьте себя
1. Чем pytest принципиально отличается от unittest по структуре теста?
AТребует больше классов
BТест — обычная функция test_* с оператором assert, без классов и assert*-методов
CНе поддерживает assert
DРаботает только в браузере
2. Почему в pytest хватает обычного assert?
Aassert там не проверяет ничего
Bpytest переписывает assert и показывает значения обеих сторон — диагностика как у assertEqual
Cpytest отключает ошибки
DЭто случайность
3. Что верно про совместимость?
Apytest несовместим с unittest
Bpytest умеет запускать и тесты, написанные на unittest
Cunittest умеет запускать pytest-тесты
DОни не работают вместе никак
Поддержать проект