


Если функция печатает результат, тестировать её только по возвращаемому значению недостаточно. Фикстура capsys в pytest позволяет прочитать перехваченные stdout и stderr и сравнить их с ожидаемым текстом. На Mentoring.digital разберём проверку двух потоков и типичную ошибку с повторным чтением.
Сохраните этот учебный пример в отдельный файл test_report.py. Он не требует сетевых запросов или доступа к рабочим данным.
import sys
def report(name):
print(f"hello {name}")
print("check input", file=sys.stderr)
def test_report(capsys):
report("Ada")
captured = capsys.readouterr()
assert captured.out == "hello Ada\n"
assert captured.err == "check input\n"
Запуск: python -m pytest -q test_report.py в окружении с установленным pytest. Параметр capsys передаёт pytest, вручную создавать его не нужно. В реальном проекте функцию обычно импортируют из модуля приложения.
Поле out содержит стандартный вывод, поле err вывод ошибок. Перенос строки после print() является частью результата, поэтому в ожидаемом значении стоит \n. Раздельные утверждения помогают понять, какой именно поток изменился.
def test_steps(capsys):
print("first")
first = capsys.readouterr()
assert first.out == "first\n"
print("second")
second = capsys.readouterr()
assert second.out == "second\n"
assert capsys.readouterr().out == ""
После снимка захват продолжается, но следующий вызов возвращает новую порцию. Не считайте, что повторное чтение снова выдаст весь предыдущий текст. Если нескольким проверкам нужен один результат, сохраните его в переменную.
Проверять точное равенство полезно, когда формат вывода является контрактом команды. Если проверяется только отдельное сообщение в более широком выводе, выбирайте утверждение под этот контракт. Автоматическое strip() может скрыть потерянный перенос или лишние пробелы, которые на самом деле важны.
capsys работает на уровне потоков Python sys.stdout и sys.stderr. Для вывода через файловые дескрипторы операционной системы, в том числе от некоторых библиотек и дочерних процессов, предназначен capfd. Его результат тоже читают через readouterr().
Для двоичных данных существуют capsysbinary и capfdbinary: они возвращают байты. Если задача состоит в проверке записей стандартного logging, сначала рассмотрите caplog, чтобы проверять сами записи и уровни, а не случайное оформление консоли.
Начните с минимального воспроизводимого теста и затем перенесите проверку в проект. Разобрать тестирование Python-кода можно с Python-ментором. Локальная проверка примера подтверждает работу захвата, но не заменяет тестирование вашей командной утилиты.