2015-06-08 37 views
5

我有這樣的示例代碼(test_it.py):丟棄標準輸出下測試程序/標準錯誤,但保留單元測試輸出

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() 

這給了我下面的輸出:

» 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) 

但由於由測試程序(真正的程序產生LOTS輸出)產生的長,煩人的消息,我無法看到unittest的輸出。我想擺脫正在測試的函數(give_me_5)的stdout/stderr,但我仍然希望看到stdout/stderr的unittest。我想得到這樣的結果:

» 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) 

因此,根據試驗(標準輸出和標準錯誤)由程序產生的輸出由單元測試,過濾掉,但輸出產生的單元測試本身保持。我不想修改正在測試的代碼(代碼本身沒有重定向)。我只想告訴unittest,所有輸出到stdout/stderr被測試的代碼應該被丟棄。

這可能嗎?

+0

可能的[python-如何重定向unittest的輸出?明顯的解決方案不起作用](http://stackoverflow.com/questions/14246119/python-how-can-i-redirect-the-output-of-unittest-obvious-solution-doesnt-wor) –

+0

@DougR。另一個問題是關於相反的問題:這個人得到了程序的輸出,單元測試的輸出被分解了,這正是我想要實現的。 – dangonfast

回答

4

暫時用文件式實例替換sys.stdoutsys.stderr。例如,您可以使用StringIO aka內存緩衝區。

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 

您可能需要添加異常處理,甚至把這個代碼在上下文管理重用它

5

@Alik的建議是正確的。但我想這可以改進。

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') 

和輸出:

I am here 
I am back 
0

僅供參考(並獲得評論),這裏是我最後使用的代碼(由@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() 

現在簡單地通過執行redirect_testcase(self),stdout/stderr被重定向到test_it.TestMe.out/test_it.TestMe.err,並且unittest的輸出在控制檯stdout/stderr(和c如果需要,可以通過shell重定向)。

存在一個問題(我還不知道如何解決):特定TestCase中的所有測試將覆蓋文件.out/.err。爲每個測試打開一個不同的輸出/日誌文件是非常好的(相對於每個測試用例的公用測試文件)

相關問題