Як надрукувати консоль у pytest?


175

Я намагаюся використовувати TDD (тестова розробка) з pytest. pytestне буде printдо консолі, коли я користуюся print.

Я використовую pytest my_tests.pyдля його запуску.

documentation, Здається, кажуть , що він повинен працювати за замовчуванням: http://pytest.org/latest/capture.html

Але:

import myapplication as tum

class TestBlogger:

    @classmethod
    def setup_class(self):
        self.user = "alice"
        self.b = tum.Blogger(self.user)
        print "This should be printed, but it won't be!"

    def test_inherit(self):
        assert issubclass(tum.Blogger, tum.Site)
        links = self.b.get_links(posts)
        print len(links)   # This won't print either.

Нічого не друкується на моїй стандартній вихідній консолі (просто нормальний хід і кількість тестів, що пройшли / провалилися).

А сценарій, який я тестую, містить друк:

class Blogger(Site):
    get_links(self, posts):
        print len(posts)   # It won't get printed in the test.

У unittestмодулі все друкується за замовчуванням, саме це мені і потрібно. Однак я хочу використовувати pytestз інших причин.

Хтось знає, як зробити так, щоб виводити заяви про друк?


1
Можливо, stdout перезаписується. Що станеться, якщо ви користуєтесь sys.stdout.write("Test")? Як щодо sys.__stdout__.write("Test")? Останній завжди повинен записувати у визначений системою stdout, який має бути консоллю. Якщо дві команди роблять різні речі, то stdout змінюється; якщо вони роблять те саме, то проблема полягає в чомусь іншому.
TheSoundDefense

Відповіді:


205

За замовчуванням py.testфіксує результат стандартного виходу, щоб він міг контролювати, як він виводить його. Якби цього не зробити, то було б виписано багато тексту без контексту тесту, який надрукував цей текст.

Однак якщо тест не вдасться, він отримає розділ у отриманому звіті, який показує, що було надруковано у стандартному тесті.

Наприклад,

def test_good():
    for i in range(1000):
        print(i)

def test_bad():
    print('this should fail!')
    assert False

Результати в наступному результаті:

>>> py.test tmp.py
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py .F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
------------------------------- Captured stdout --------------------------------
this should fail!
====================== 1 failed, 1 passed in 0.04 seconds ======================

Зверніть увагу на Captured stdoutрозділ.

Якщо ви хочете побачити printзаяви, як вони виконуються, ви можете передати -sпрапор py.test. Однак зауважте, що іноді це може бути важко проаналізувати.

>>> py.test tmp.py -s
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py 0
1
2
3
... and so on ...
997
998
999
.this should fail!
F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
====================== 1 failed, 1 passed in 0.02 seconds ======================

2
Надзвичайно практичний. Чудова робота!
cmc

1
Хм ... все ще не записую мої заяви про друк
Тім Боланд

68

Використовуючи -sпараметр, буде надруковано вихід всіх функцій, що може бути занадто багато.

Якщо вам потрібен конкретний вихід, на згаданій вами сторінці документа ви знайдете кілька пропозицій:

  1. Вставте assert False, "dumb assert to make PyTest print my stuff"в кінці своєї функції, і ви побачите свій результат через невдалий тест.

  2. У вас є спеціальний об'єкт, переданий вам PyTest, і ви можете записати вихід у файл, щоб перевірити його пізніше, наприклад

    def test_good1(capsys):
        for i in range(5):
            print i
        out, err = capsys.readouterr()
        open("err.txt", "w").write(err)
        open("out.txt", "w").write(out)

    Ви можете відкрити файли outта errфайли на окремій вкладці і дозволити редактору автоматично оновити її для вас, або виконати просту py.test; cat out.txtкоманду оболонки, щоб запустити тест.

Це досить хакерський спосіб робити речі, але, можливо, саме такі речі вам потрібні: зрештою, TDD означає, що ви псуєтесь із речами та залишаєте його чистим і безшумним, коли він готовий :-).


Я спробував версію 1. з pytest 3.8.1, на жаль, він друкує лише тестовий функціональний блок, але не вихід із заяв про друк :( будь-які прийоми для цього?
УВ,

@UV - Замість використання print()функції слід вставити змінну або повідомлення, яке ви хочете надрукувати після коми в операторі затвердження. Наприклад assert False, what_are_you, "роздрукується" значення what_are_youу звіті про пістет.
Март Ван де Вен

43

Коротка відповідь

Скористайтеся -sопцією:

pytest -s

Детальна відповідь

З документів :

Під час виконання тесту будь-який вихід, відправлений у stdout та stderr , фіксується. Якщо тест або метод налаштування не вдається, його зазвичай відображається разом із відтвореним результатом, а також відстеженням відмови.

pytestмає можливість , --capture=methodв якому methodзнаходиться за випробування методу захоплення, і може бути одним з наступних: fd, sysабо no. pytestтакож є опція, для -sякої це ярлик --capture=no, і це параметр, який дозволить вам бачити ваші твердження про друк на консолі.

pytest --capture=no     # show print statements in console
pytest -s               # equivalent to previous command

Встановлення методів захоплення або відключення захоплення

Є два способи pytestздійснення захоплення:

  1. захоплення рівня дескриптора файлів (FD) (за замовчуванням): Усі записи, що надходять у дескриптори файлів 1 і 2 операційної системи, будуть захоплені.

  2. захоплення рівня sys : Лише записує у файли Python sys.stdout та sys.stderr. Ніякого захоплення записів до поданих сценаріїв не проводиться.

pytest -s            # disable all capturing
pytest --capture=sys # replace sys.stdout/stderr with in-mem files
pytest --capture=fd  # also point filedescriptors 1 and 2 to temp file

17

Мені потрібно було надрукувати важливе попередження про пропущені тести саме тоді, коли PyTestвимкнено буквально все .

Я не хотів провалити тест, щоб надіслати сигнал, тому зробив хак, як слід:

def test_2_YellAboutBrokenAndMutedTests():
    import atexit
    def report():
        print C_patch.tidy_text("""
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.""")
    if sys.stdout != sys.__stdout__:
        atexit.register(report)

atexitМодуль дозволяє мені друкувати матеріал після PyTest звільнили вихідні потоки. Вихід виглядає так:

============================= test session starts ==============================
platform linux2 -- Python 2.7.3, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /media/Storage/henaro/smyth/Alchemist2-git/sources/C_patch, inifile: 
collected 15 items 

test_C_patch.py .....ssss....s.

===================== 10 passed, 5 skipped in 0.15 seconds =====================
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.
~/.../sources/C_patch$

Повідомлення друкується навіть PyTestу безшумному режимі, і не друкується, якщо ви працюєте з файлами py.test -s, тому все вже перевірено.


1
Ідеально підходить для виведення спеціальних тестових показників.
z0r


2

Я спочатку зайшов сюди, щоб знайти, як зробити PyTestдрук у консолі VSCode під час запуску / налагодження тестового блоку звідти. Це можна зробити за допомогою наступної launch.jsonконфігурації. З огляду .venvна папку віртуального середовища.

    "version": "0.2.0",
    "configurations": [
        {
            "name": "PyTest",
            "type": "python",
            "request": "launch",
            "stopOnEntry": false,
            "pythonPath": "${config:python.pythonPath}",
            "module": "pytest",
            "args": [
                "-sv"
            ],
            "cwd": "${workspaceRoot}",
            "env": {},
            "envFile": "${workspaceRoot}/.venv",
            "debugOptions": [
                "WaitOnAbnormalExit",
                "WaitOnNormalExit",
                "RedirectOutput"
            ]
        }
    ]
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.