Bagaimana cara mencetak ke konsol di pytest?

175

Saya mencoba menggunakan TDD (test-driven development) dengan pytest. pytesttidak akan printke konsol saat saya gunakan print.

Saya menggunakan pytest my_tests.pyuntuk menjalankannya.

The documentationtampaknya mengatakan bahwa itu harus bekerja secara default: http://pytest.org/latest/capture.html

Tapi:

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.

Tidak ada yang dicetak ke konsol keluaran standar saya (hanya kemajuan normal dan berapa banyak tes yang lulus / gagal).

Dan skrip yang saya uji berisi cetak:

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

Dalam unittestmodul, semuanya akan dicetak secara default, yang persis saya butuhkan. Namun, saya ingin menggunakan pytestuntuk alasan lain.

Apakah ada yang tahu cara membuat laporan cetak ditampilkan?

BBedit
sumber
1
Mungkin stdout sedang ditimpa. Apa yang terjadi jika Anda menggunakan sys.stdout.write("Test")? Bagaimana dengan sys.__stdout__.write("Test")? Yang terakhir harus selalu menulis ke stdout yang ditentukan sistem, yang seharusnya menjadi konsol. Jika kedua perintah melakukan hal yang berbeda, maka stdout sedang diubah; jika mereka melakukan hal yang sama, maka masalahnya adalah hal lain.
TheSoundDefense

Jawaban:

205

Secara default, py.testtangkap hasil dari out standar sehingga dapat mengontrol bagaimana mencetaknya. Jika tidak melakukan ini, itu akan memuntahkan banyak teks tanpa konteks tes apa yang dicetak teks itu.

Namun, jika tes gagal, itu akan mencakup bagian dalam laporan yang dihasilkan yang menunjukkan apa yang dicetak dengan standar dalam tes tertentu.

Sebagai contoh,

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

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

Hasil dalam output berikut:

>>> 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 ======================

Perhatikan Captured stdoutbagian ini.

Jika Anda ingin melihat printpernyataan ketika dieksekusi, Anda dapat meneruskannya ke -sbendera py.test. Namun, perhatikan bahwa ini terkadang sulit untuk diurai.

>>> 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 ======================
tbekolay
sumber
2
Sangat praktis. Kerja bagus!
cmc
1
hmm ... masih belum mencatat pernyataan cetak saya
Tim Boland
68

-sOpsi menggunakan akan mencetak output dari semua fungsi, yang mungkin terlalu banyak.

Jika Anda membutuhkan hasil tertentu, halaman dokumen yang Anda sebutkan menawarkan beberapa saran:

  1. Masukkan assert False, "dumb assert to make PyTest print my stuff"di akhir fungsi Anda, dan Anda akan melihat output Anda karena gagal tes.

  2. Anda memiliki objek khusus yang dikirimkan kepada Anda oleh PyTest, dan Anda dapat menulis output ke file untuk memeriksanya nanti, seperti

    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)

    Anda dapat membuka outdan errfile di tab terpisah dan membiarkan editor secara otomatis menyegarkan untuk Anda, atau melakukan py.test; cat out.txtperintah shell sederhana untuk menjalankan pengujian Anda.

Itu cara yang agak lunak untuk melakukan hal-hal, tetapi mungkin itu adalah hal yang Anda butuhkan: lagipula, TDD berarti Anda mengacaukan barang-barang dan membiarkannya tetap bersih dan diam ketika sudah siap :-).

dmitry_romanov
sumber
saya mencoba versi 1. dengan pytest 3.8.1 sayangnya hanya mencetak blok fungsi tes, tetapi bukan output dari pernyataan cetak :( ada lagi trik untuk ini?
UV
@UV - Alih-alih menggunakan print()fungsi, Anda harus meletakkan variabel atau pesan yang ingin Anda cetak setelah koma dalam pernyataan tegas. Misalnya assert False, what_are_youakan 'mencetak' nilai what_are_youdalam laporan pytest.
Mart Van de Ven
43

Jawaban singkat

Gunakan -sopsi:

pytest -s

Jawaban terinci

Dari dokumen :

Selama pelaksanaan pengujian, output apa pun yang dikirim ke stdout dan stderr ditangkap. Jika pengujian atau metode pengaturan gagal, keluaran yang ditangkap biasanya akan ditampilkan bersama dengan kegagalan traceback.

pytestmemiliki opsi --capture=methodyang methodmerupakan per-test metode menangkap, dan bisa menjadi salah satu dari berikut ini: fd, sysatau no. pytestjuga memiliki opsi -syang merupakan jalan pintas --capture=no, dan ini adalah opsi yang akan memungkinkan Anda untuk melihat laporan cetak Anda di konsol.

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

Mengatur metode pengambilan atau menonaktifkan pengambilan

Ada dua cara untuk pytestmelakukan penangkapan:

  1. pengambilan file deskriptor (FD) level capturing (default): Semua penulisan yang masuk ke file sistem operasi deskriptor 1 dan 2 akan ditangkap.

  2. menangkap level sys : Hanya menulis ke file Python sys.stdout dan sys.stderr akan ditangkap. Pengambilan penulisan ke pengarsipan tidak dilakukan.

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
lmiguelvargasf
sumber
17

Saya perlu mencetak peringatan penting tentang tes yang dilewati tepat ketika PyTestsecara harfiah mematikan semuanya .

Saya tidak ingin gagal dalam tes untuk mengirim sinyal, jadi saya melakukan hack sebagai berikut:

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)

The atexitmodul memungkinkan saya untuk mencetak barang-barang setelah PyTest merilis output stream. Outputnya terlihat sebagai berikut:

============================= 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$

Pesan dicetak bahkan ketika PyTestberada dalam mode diam, dan tidak dicetak jika Anda menjalankan sesuatu dengan py.test -s, jadi semuanya sudah diuji dengan baik.

dmitry_romanov
sumber
1
Sempurna untuk menghasilkan metrik pengujian khusus.
z0r
5

Menurut dokumen pytest , pytest --capture=sysharus bekerja. Jika Anda ingin menangkap standar di dalam tes, lihat perlengkapan capsys.

Karthik Gomadam Rajagopal
sumber
Ini bekerja untuk saya ketika perlu mencetak variabel di terminal ...
Sukma Saputra
2

Saya awalnya datang ke sini untuk menemukan cara membuat PyTestcetak di konsol VSCode saat menjalankan / men-debug unit test dari sana. Ini dapat dilakukan dengan launch.jsonkonfigurasi berikut . Diberikan .venvfolder lingkungan virtual.

    "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"
            ]
        }
    ]
}
dummyDev
sumber