Написание функции pytest для проверки вывода на консоль (stdout)

В этой ссылке дается описание использования pytest для захвата выходов консоли. Я пробовал этот следующий простой код, но получаю ошибку

import sys
import pytest
def f(name):
    print "hello "+ name

def test_add(capsys):
    f("Tom")
    out,err=capsys.readouterr()
    assert out=="hello Tom"


test_add(sys.stdout)

Вывод:

python test_pytest.py 
hello Tom
Traceback (most recent call last):
  File "test_pytest.py", line 12, in <module>
    test_add(sys.stdout)
  File "test_pytest.py", line 8, in test_add
    out,err=capsys.readouterr()
AttributeError: 'file' object has no attribute 'readouterr'

что не так и какое исправление необходимо? спасибо

EDIT: В соответствии с комментарием я изменил capfd, но я все равно получаю ту же ошибку

import sys
import pytest
def f(name):
    print "hello "+ name

def test_add(capfd):
    f("Tom")
    out,err=capfd.readouterr()
    assert out=="hello Tom"


test_add(sys.stdout)

Ответ 1

Используйте приспособление capfd.

Пример:

def test_foo(capfd):
    foo()  # Writes "Hello World!" to stdout
    out, err = capfd.readouterr()
    assert out == "Hello World!"

Смотрите: http://pytest.org/latest/fixture.html для более подробной информации

И посмотрите: py.test --fixtures для списка встроенных приборов.

В вашем примере есть несколько проблем. Вот исправленная версия:

def f(name):
    print "hello {}".format(name)


def test_f(capfd):
    f("Tom")

    out, err = capfd.readouterr()
    assert out == "hello Tom\n"

Замечания:

  • Не используйте sys.stdout - Используйте приспособление capfd как есть, как это предусмотрено pytest.
  • Запустите тест с помощью: py.test foo.py

Результат тестового прогона:

$ py.test foo.py
====================================================================== test session starts ======================================================================
platform linux2 -- Python 2.7.5 -- pytest-2.4.2
plugins: flakes, cache, pep8, cov
collected 1 items 

foo.py .

=================================================================== 1 passed in 0.01 seconds ====================================================================

Также обратите внимание:

  • Вам не нужно запускать ваши тестовые функции в ваших тестовых модулях. py.test (инструмент CLI и Test Runner) сделает это за вас.

py.test в основном делает три вещи:

  1. Собери свои тесты
  2. Запустите ваши тесты
  3. Показать статистику и, возможно, ошибки

По умолчанию py.test ищет (конфигурируемый IIRC) test_foo.py тестовых модули и test_foo() функцию тестирования в тестовых модулях.

Ответ 2

Проблема заключается в вашем явном вызове вашей тестовой функции в самом конце первого блока фрагмента кода:

test_add(sys.stdout)

Вы не должны этого делать; это задача pytest для вызова ваших тестовых функций. Когда это произойдет, оно распознает имя capsys (или capfd, если на то пошло) и автоматически предоставляют подходящий внутренний объект pytest для вас в качестве аргумента вызова. (пример, приведенный в документации pytest, является довольно полным, как есть.)

Этот объект предоставит требуемую функцию readouterr(). sys.stdout не имеет этой функции, поэтому ваша программа не работает.