2015-06-08 18 views
5

Tôi có mẫu này mã (test_it.py):Huỷ stdout/stderr của chương trình theo kiểm tra, nhưng giữ unittest đầu ra

import sys 

def give_me_5(): 
    print >>sys.stdout, "STDOUT" 
    print >>sys.stderr, "STDERR" 
    return 6 

import unittest 


class TestMe(unittest.TestCase): 

    def setUp(self): 
     pass 

    def test_give_me_5(self): 
     self.assertEqual(give_me_5(), 5) 


if __name__ == '__main__': 
    unittest.main() 

nào mang lại cho tôi kết quả như sau:

» python -m unittest test_it 
A long annoying output message 
A long annoying error message 
F 
====================================================================== 
FAIL: test_give_me_5 (__main__.TestMe) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "xx.py", line 17, in test_give_me_5 
    self.assertEqual(give_me_5(), 5) 
AssertionError: 6 != 5 

---------------------------------------------------------------------- 
Ran 1 test in 0.000s 

FAILED (failures=1) 

Nhưng vì sự tin nhắn dài, gây phiền nhiễu được sản xuất bởi chương trình đang được kiểm tra (chương trình thực sự tạo ra LOTS của đầu ra), tôi không thể nhìn thấy đầu ra từ unittest. Tôi muốn loại bỏ stdout/stderr của hàm đang được kiểm tra (give_me_5), nhưng tôi vẫn muốn xem stdout/stderr của unittest. Tôi muốn để có được kết quả này:

» python -m unittest test_it 
F 
====================================================================== 
FAIL: test_give_me_5 (__main__.TestMe) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "xx.py", line 17, in test_give_me_5 
    self.assertEqual(give_me_5(), 5) 
AssertionError: 6 != 5 

---------------------------------------------------------------------- 
Ran 1 test in 0.000s 

FAILED (failures=1) 

Vì vậy mà sản lượng sản xuất bởi các chương trình được kiểm tra (cả stdout và stderr) được lọc ra bởi unittest, nhưng sản lượng sản xuất bởi unittest bản thân được giữ. Tôi không muốn sửa đổi mã đang được thử nghiệm (không có chuyển hướng trong chính mã). Tôi chỉ muốn nói với unittest rằng tất cả các đầu ra để stdout/stderr được tạo ra bởi các mã được kiểm tra nên được loại bỏ.

Điều này có khả thi không?

+0

bản sao có thể có của [python - làm cách nào để chuyển hướng đầu ra của unittest? Giải pháp rõ ràng không hoạt động] (http://stackoverflow.com/questions/14246119/python-how-can-i-redirect-the-output-of-unittest-obvious-solution-doesnt-wor) –

+0

@DougR. Đó là câu hỏi khác là về vấn đề ngược lại: anh chàng đã nhận được đầu ra của chương trình và đầu ra của unittest tách ra, đó là chính xác những gì tôi muốn đạt được. – dangonfast

Trả lời

4

Tạm thời thay thế sys.stdoutsys.stderr bằng các trường hợp giống như tệp. Ví dụ: bạn có thể sử dụng StringIO hay còn gọi là bộ nhớ đệm.

from StringIO import StringIO 

..... 


class TestMe(unittest.TestCase): 

    def setUp(self): 
     pass 

    def test_give_me_5(self): 

     stdout = sys.stdout 
     stderr = sys.stderr 

     sys.stdout = StringIO() 
     sys.stderr = StringIO() 

     self.assertEqual(give_me_5(), 5) 

     sys.stdout = stdout 
     sys.stderr = stderr 

Bạn có thể muốn thêm xử lý ngoại lệ hoặc thậm chí biến mã này trong một trình quản lý bối cảnh để tái sử dụng nó

5

@Alik gợi ý đã đúng. Nhưng tôi đoán nó có thể được cải thiện.

import sys 
# StringIO is replaced in Python 3: 
try: 
    from StringIO import StringIO 
except ImportError: 
    from io import StringIO 

class ReplaceStd(object): 
    """ Let's make it pythonic. """ 

    def __init__(self): 
     self.stdout = None 
     self.stderr = None 

    def __enter__(self): 
     self.stdout = sys.stdout 
     self.stderr = sys.stderr 

     # as it was suggseted already: 
     sys.stdout = StringIO() 
     sys.stderr = StringIO() 

    def __exit__(self, type, value, traceback): 
     sys.stdout = self.stdout 
     sys.stderr = self.stderr 

print('I am here') 
with ReplaceStd(): 
    print('I am not') 

print('I am back') 

Và kết quả:

I am here 
I am back 
0

Để tham khảo (và lấy ý kiến), đây là đoạn code tôi đã kết thúc bằng cách sử dụng (lấy cảm hứng từ trong trả lời bởi @Alik):

import sys 

def give_me_5(): 
    print >>sys.stdout, "A long annoying output message" 
    print >>sys.stderr, "A long annoying error message" 
    return 6 


import unittest 

def redirect(stdout_file=None, stderr_file=None): 
    new_stdout = open(stdout_file, 'w') if stdout_file else None 
    new_stderr = open(stderr_file, 'w') if stderr_file else None 
    if new_stdout : sys.stdout = new_stdout 
    if new_stderr : sys.stderr = new_stderr 

def redirect_testcase(test_case): 
    logfile = '.'.join([test_case.__module__, test_case.__class__.__name__, 'out']) 
    errfile = '.'.join([test_case.__module__, test_case.__class__.__name__, 'err']) 
    redirect(logfile, errfile) 


class TestMe(unittest.TestCase): 

    def setUp(self): 
     redirect_testcase(self) 

    def test_give_me_5(self): 
     self.assertEqual(give_me_5(), 5) 

if __name__ == '__main__': 
    unittest.main() 

Bây giờ chỉ đơn giản bằng cách thực hiện một redirect_testcase(self), stdout/stderr được chuyển đến test_it.TestMe.out/test_it.TestMe.err, và đầu ra từ unittest được hiển thị trong giao diện điều khiển stdout/stderr (và c được chuyển hướng qua shell nếu cần).

Có sự cố (tôi chưa biết cách khắc phục): tất cả các thử nghiệm trong một TestCase cụ thể sẽ ghi đè các tệp .out/.err. Sẽ tốt hơn nếu mở một tệp nhật ký/tệp nhật ký khác cho mỗi bài kiểm tra (trái với một bài kiểm tra chung cho mỗi TestCase)

Các vấn đề liên quan