Trong một bình luận được đánh giá cao cho câu trả lời được chấp nhận , Joe hỏi:
Có cách nào để in ra bàn điều khiển VÀ nắm bắt đầu ra để nó hiển thị trong báo cáo Junit không?
Trong UNIX, điều này thường được gọi là teeing . Lý tưởng nhất là phát bóng thay vì chụp sẽ là mặc định py.test. Không lý tưởng, không phải py.test hay bất kỳ plugin py.test của bên thứ ba nào hiện có (... mà tôi biết, dù sao ) cũng hỗ trợ phát bóng - mặc dù Python hỗ trợ rất nhiều cho việc phát bóng ngoài luồng .
Khỉ vá py.test để làm bất cứ điều gì không được hỗ trợ là không tầm thường. Tại sao? Bởi vì:
- Hầu hết các chức năng py.test bị khóa đằng sau một
_pytest
gói riêng không có ý định nhập bên ngoài. Cố gắng làm như vậy mà không biết những gì bạn đang làm thường dẫn đến pytest
gói công khai làm tăng các ngoại lệ tối nghĩa khi chạy. Cảm ơn rất nhiều, py.test. Kiến trúc thực sự mạnh mẽ bạn đã có ở đó.
- Ngay cả khi bạn làm con số ra làm thế nào để con khỉ-vá các tin
_pytest
API một cách an toàn, bạn cần phải làm như vậy trước khi chạy công pytest
gói chạy bởi bên ngoài py.test
lệnh. Bạn không thể làm điều này trong một plugin (ví dụ: conftest
mô-đun cấp cao nhất trong bộ thử nghiệm của bạn). Vào thời điểm py.test lười biếng bắt đầu nhập động plugin của bạn, bất kỳ lớp py.test nào bạn muốn vá khỉ đã được khởi tạo từ lâu - và bạn không có quyền truy cập vào trường hợp đó. Điều này ngụ ý rằng, nếu bạn muốn bản vá khỉ của mình được áp dụng một cách có ý nghĩa, bạn không còn có thể chạy py.test
lệnh bên ngoài một cách an toàn . Thay vào đó, bạn phải kết thúc việc chạy lệnh đó bằng một setuptools tùy chỉnhtest
lệnh đó (theo thứ tự):
- Khỉ vá các
_pytest
API riêng .
- Gọi
pytest.main()
chức năng công cộng để chạy py.test
lệnh.
Câu trả lời này cho khỉ-patch py.test -s
và --capture=no
các tùy chọn để chụp stderr nhưng không xuất sắc. Theo mặc định, các tùy chọn này không bắt được thiết bị xuất chuẩn cũng như thiết bị xuất chuẩn. Điều này không hẳn là phát bóng, tất nhiên. Nhưng mọi hành trình vĩ đại đều bắt đầu với một phần tiền truyện tẻ nhạt mà mọi người đều quên trong năm năm.
Tại sao làm điều này? Bây giờ tôi sẽ nói với bạn. Bộ kiểm tra hướng py.test của tôi chứa các bài kiểm tra chức năng chậm. Hiển thị thiết bị xuất chuẩn của các thử nghiệm này rất hữu ích và yên tâm, ngăn không cho leycec tiếp cận killall -9 py.test
khi một thử nghiệm chức năng chạy dài khác không thể làm gì trong nhiều tuần. Tuy nhiên, việc hiển thị các tiêu chuẩn của các thử nghiệm này sẽ ngăn py.test báo cáo các dấu vết ngoại lệ về các lỗi thử nghiệm. Mà là hoàn toàn không có ích. Do đó, chúng tôi ép buộc py.test để bắt stderr nhưng không xuất sắc.
Trước khi chúng tôi nhận được nó, câu trả lời này giả định rằng bạn đã có test
lệnh setuptools tùy chỉnh gọi py.test. Nếu bạn không, hãy xem phần phụ Tích hợp thủ công của trang Thực hành tốt được viết tốt của py.test .
Đừng không cài đặt pytest-Á hậu , một setuptools của bên thứ ba plug-in cung cấp một setuptools tùy chỉnh test
cũng lệnh gọi py.test. Nếu pytest-runner đã được cài đặt, có lẽ bạn sẽ cần gỡ cài đặt gói pip3 đó và sau đó áp dụng phương pháp thủ công được liên kết ở trên.
Giả sử bạn đã làm theo các hướng dẫn trong Tích hợp thủ công được tô sáng ở trên, cơ sở mã của bạn bây giờ sẽ chứa một PyTest.run_tests()
phương thức. Sửa đổi phương pháp này cho giống:
class PyTest(TestCommand):
.
.
.
def run_tests(self):
# Import the public "pytest" package *BEFORE* the private "_pytest"
# package. While importation order is typically ignorable, imports can
# technically have side effects. Tragicomically, that is the case here.
# Importing the public "pytest" package establishes runtime
# configuration required by submodules of the private "_pytest" package.
# The former *MUST* always be imported before the latter. Failing to do
# so raises obtuse exceptions at runtime... which is bad.
import pytest
from _pytest.capture import CaptureManager, FDCapture, MultiCapture
# If the private method to be monkey-patched no longer exists, py.test
# is either broken or unsupported. In either case, raise an exception.
if not hasattr(CaptureManager, '_getcapture'):
from distutils.errors import DistutilsClassError
raise DistutilsClassError(
'Class "pytest.capture.CaptureManager" method _getcapture() '
'not found. The current version of py.test is either '
'broken (unlikely) or unsupported (likely).'
)
# Old method to be monkey-patched.
_getcapture_old = CaptureManager._getcapture
# New method applying this monkey-patch. Note the use of:
#
# * "out=False", *NOT* capturing stdout.
# * "err=True", capturing stderr.
def _getcapture_new(self, method):
if method == "no":
return MultiCapture(
out=False, err=True, in_=False, Capture=FDCapture)
else:
return _getcapture_old(self, method)
# Replace the old with the new method.
CaptureManager._getcapture = _getcapture_new
# Run py.test with all passed arguments.
errno = pytest.main(self.pytest_args)
sys.exit(errno)
Để kích hoạt bản vá khỉ này, hãy chạy py.test như sau:
python setup.py test -a "-s"
Stderr nhưng không stdout bây giờ sẽ bị bắt. Tiện lợi!
Mở rộng bản vá khỉ ở trên sang tee stdout và stderr được để lại cho người đọc với một thùng đầy thời gian rảnh.