วิธีการพิมพ์ไปยังคอนโซลใน pytest?


175

ฉันพยายามที่จะใช้ TDD (ทดสอบขับเคลื่อนการพัฒนา) pytestด้วย pytestจะไม่ไปยังคอนโซลเมื่อฉันใช้printprint

ฉันใช้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

@UV - แทนที่จะใช้print()ฟังก์ชันคุณควรใส่ตัวแปรหรือข้อความที่คุณต้องการพิมพ์ หลังเครื่องหมายจุลภาคในคำสั่ง assert เช่นassert False, what_are_youจะ 'พิมพ์' มูลค่าของwhat_are_youรายงาน pytest
Mart Van de Ven

43

คำตอบสั้น ๆ

ใช้-sตัวเลือก:

pytest -s

คำตอบโดยละเอียด

จากเอกสาร :

ในระหว่างการดำเนินการทดสอบเอาต์พุตใด ๆ ที่ส่งไปยังstdoutและstderrจะถูกดักจับ หากการทดสอบหรือวิธีการตั้งค่าล้มเหลวเอาต์พุตที่จับตามปกติจะแสดงพร้อมกับการติดตามย้อนกลับที่ล้มเหลว

pytestมีตัวเลือก--capture=methodในการที่methodเป็นวิธีการจับต่อการทดสอบและอาจจะเป็นหนึ่งต่อไปนี้: fd, หรือsys มีตัวเลือกซึ่งเป็นทางลัดสำหรับและนี่คือตัวเลือกที่จะช่วยให้คุณเห็นคำสั่งการพิมพ์ของคุณในคอนโซลnopytest-s--capture=no

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

การตั้งค่าวิธีการถ่ายภาพหรือปิดใช้งานการถ่ายภาพ

มีสองวิธีที่pytestสามารถทำการจับภาพได้:

  1. การจับภาพระดับ file descriptor (FD) (ค่าเริ่มต้น): การเขียนทั้งหมดที่ไปยังตัวอธิบายไฟล์ระบบปฏิบัติการ 1 และ 2 จะถูกบันทึก

  2. การจับภาพระดับ sys : เขียนไปยังไฟล์ Python เท่านั้น sys.stdout และ sys.stderr จะถูกดักจับ ไม่มีการจับการเขียนไปยัง filescriptors

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

5

อ้างอิงถึงเอกสาร pytest , pytest --capture=sysควรจะทำงาน หากคุณต้องการจับภาพมาตรฐานในการทดสอบให้ดูที่การแข่งขัน capsys


มันใช้งานได้สำหรับฉันเมื่อต้องการตัวแปรการพิมพ์ในเทอร์มินัล ...
Sukma Saputra

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"
            ]
        }
    ]
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.