Чем удобен 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
| Аспект | unittest | pytest |
| структура теста | класс + методы | просто функция |
| проверка | 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-тесты.