Làm thế nào để in ra bàn điều khiển trong pytest?


174

Tôi đang cố gắng sử dụng TDD (phát triển dựa trên thử nghiệm) với pytest. pytestsẽ không printđến bàn điều khiển khi tôi sử dụng print.

Tôi đang sử dụng pytest my_tests.pyđể chạy nó.

Các documentationdường như để nói rằng nó sẽ hoạt động theo mặc định: http://pytest.org/latest/capture.html

Nhưng:

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.

Không có gì được in vào bảng điều khiển đầu ra tiêu chuẩn của tôi (chỉ là tiến trình bình thường và có bao nhiêu bài kiểm tra đã vượt qua / thất bại).

Và tập lệnh mà tôi đang kiểm tra có chứa bản in:

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

Trong unittestmô-đun, mọi thứ được in theo mặc định, đó chính xác là những gì tôi cần. Tuy nhiên, tôi muốn sử dụng pytestcho các lý do khác.

Có ai biết làm thế nào để làm cho các báo cáo in được hiển thị?


1
Có lẽ stdout đang bị ghi đè. Điều gì xảy ra nếu bạn sử dụng sys.stdout.write("Test")? Thế còn sys.__stdout__.write("Test")? Cái sau phải luôn luôn ghi vào thiết bị xuất chuẩn do hệ thống xác định, nên là bàn điều khiển. Nếu hai lệnh làm những việc khác nhau, thì thiết bị xuất chuẩn sẽ bị thay đổi; nếu họ làm điều tương tự, thì vấn đề là một cái gì đó khác.
TheSoundDefense

Câu trả lời:


205

Theo mặc định, py.testchụp kết quả của tiêu chuẩn để nó có thể kiểm soát cách in ra. Nếu nó không làm điều này, nó sẽ phun ra rất nhiều văn bản mà không có bối cảnh của bài kiểm tra in văn bản đó.

Tuy nhiên, nếu thử nghiệm thất bại, nó sẽ bao gồm một phần trong báo cáo kết quả cho thấy những gì đã được in ra theo tiêu chuẩn trong thử nghiệm cụ thể đó.

Ví dụ,

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

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

Kết quả trong đầu ra sau:

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

Lưu ý Captured stdoutphần.

Nếu bạn muốn xem các printcâu lệnh khi chúng được thực thi, bạn có thể chuyển -scờ tới py.test. Tuy nhiên, lưu ý rằng điều này đôi khi có thể khó phân tích.

>>> 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
Eminently thực tế. Bạn đã làm rất tốt!
cmc

1
hmm ... vẫn không ghi nhật ký in của tôi
Tim Boland

67

Sử dụng -stùy chọn sẽ in đầu ra của tất cả các chức năng, có thể quá nhiều.

Nếu bạn cần đầu ra cụ thể, trang tài liệu bạn đề cập cung cấp một vài gợi ý:

  1. Chèn assert False, "dumb assert to make PyTest print my stuff"vào cuối chức năng của bạn và bạn sẽ thấy đầu ra của mình do thử nghiệm thất bại.

  2. Bạn có đối tượng đặc biệt được PyTest chuyển cho bạn và bạn có thể ghi kết quả đầu ra vào một tệp để kiểm tra nó sau, như

    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)

    Bạn có thể mở outerrcác tệp trong một tab riêng biệt và để trình soạn thảo tự động làm mới nó cho bạn hoặc thực hiện một py.test; cat out.txtlệnh shell đơn giản để chạy thử nghiệm của bạn.

Đó là cách khá rắc rối để làm công cụ, nhưng có thể đó là thứ bạn cần: sau tất cả, TDD có nghĩa là bạn lộn xộn với công cụ và để nó sạch sẽ và im lặng khi nó sẵn sàng :-).


Tôi đã thử phiên bản 1. với pytest 3.8.1, thật không may, nó chỉ in khối chức năng kiểm tra, nhưng không xuất ra từ các câu lệnh in :( còn thủ thuật nào nữa không?
UV

@UV - Thay vì sử dụng print()hàm, bạn nên đặt biến hoặc thông báo bạn muốn in sau dấu phẩy trong câu lệnh khẳng định. Ví dụ: assert False, what_are_you'in ra' giá trị của what_are_youtrong báo cáo pytest.
Mart Van de Ven

43

Câu trả lời ngắn

Sử dụng -stùy chọn:

pytest -s

Câu trả lời chi tiết

Từ các tài liệu :

Trong quá trình thực hiện kiểm tra, bất kỳ đầu ra nào được gửi tới thiết bị xuất chuẩnthiết bị xuất chuẩn sẽ được ghi lại. Nếu một thử nghiệm hoặc một phương thức thiết lập không thành công, thì đầu ra bị bắt thường sẽ được hiển thị cùng với truy nguyên lỗi.

pytestcó tùy chọn --capture=methodtrong đó methodlà phương pháp chụp theo thử nghiệm và có thể là một trong các cách sau : fd, syshoặc no. pytestcũng có tùy chọn -slà lối tắt cho --capture=novà đây là tùy chọn cho phép bạn xem các câu lệnh in của mình trong bảng điều khiển.

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

Đặt phương thức chụp hoặc tắt chức năng chụp

Có hai cách để pytestcó thể thực hiện chụp:

  1. Chụp mức mô tả tệp (FD) (mặc định): Tất cả ghi vào hệ thống mô tả tệp hệ điều hành 1 và 2 sẽ được ghi lại.

  2. Chụp mức sys : Chỉ ghi vào tệp Python sys.stdout và sys.stderr sẽ được ghi lại. Không có ghi lại ghi vào filedescriptors được thực hiện.

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

Tôi cần in cảnh báo quan trọng về các bài kiểm tra bị bỏ qua chính xác khi PyTesttắt tiếng mọi thứ theo nghĩa đen .

Tôi không muốn thất bại trong một bài kiểm tra để gửi tín hiệu, vì vậy tôi đã thực hiện một hack như sau:

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)

Các atexitmô-đun cho phép tôi để in những thứ sau khi PyTest phát hành các dòng đầu ra. Đầu ra trông như sau:

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

Tin nhắn được in ngay cả khi PyTestở chế độ im lặng và không được in nếu bạn chạy nội dung py.test -s, vì vậy mọi thứ đã được kiểm tra độc đáo.


1
Hoàn hảo để xuất các số liệu kiểm tra tùy chỉnh.
z0r


2

Ban đầu tôi đến đây để tìm cách PyTestin trong bảng điều khiển của VSCode trong khi chạy / gỡ lỗi bài kiểm tra đơn vị từ đó. Điều này có thể được thực hiện với launch.jsoncấu hình sau . Cho .venvthư mục môi trường ảo.

    "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"
            ]
        }
    ]
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.