2016-11-13 113 views
0

在測試中,我將stderr重定向到文件中,並嘗試以尾巴式方式讀取它。 因此,這裏是重定向:Python尾狀文件讀取

class RedirectedEnv(object): 
    def __init__(self, stderr=None): 
     self._stderr = stderr or sys.stderr 

    def __enter__(self): 
     self.old_stderr = sys.stderr 
     self.old_stderr.flush() 
     self.old_exit = getattr(sys, 'exit') 
     sys.stderr = self._stderr 

     def mock_exit(): 
      raise Exception 
     sys.exit = mock_exit 

    def __exit__(self, exc_type, exc_val, exc_tb): 
     self._stderr.flush() 
     sys.stderr = self.old_stderr 
     sys.exit = self.old_exit 

     self._stderr.close() 

和它的用法:

def test_invalid_args(self): 
    with RedirectedEnv(stderr=tempfile.NamedTemporaryFile()): 
     for args in [['-id', '123456789.00'], ['-i'], ['-i', '0'], ['-i', '../some_invalid_path/not_exist.json']]: 
      try: 
       self.parser.parse(args) 
      except Exception: 
       sys.stderr.flush() 
       self.assertTrue(sys.stderr.readlines()[0].startswith("usage:")) <<-- here I need help 

是否有某種優雅的方式來做到這一點? (不要弄得enumeratetell()seek())也許有一些FIFO queue與文件接口?

+0

修復類定義中的縮進 – Leva7

+0

爲什麼'seek'亂七八糟?不應該'try'在每個循環中截斷文件,並且不應該將異常尋找到文件的前面並讀取一行?你的測試案例有點奇怪,它捕獲了所有的異常,但似乎沒有區分選項列表何時應該引發異常和何時不應該引發異常。這些測試中的一些應該通過而其他測試失敗? – tdelaney

+0

所有應該失敗。我嘲笑sys.exit以防止argparser退出解釋器,檢查正確的使用信息。也許這不是最好的方法)我用「wb +」打開文件,它添加內容到最後,而不是重寫它,所以我不能只求偏移量= 0。我錯過了什麼嗎? – Constantine

回答

1

您可以爲每個測試創建一個新文件,然後在前面尋找它的價值。由於您不使用文件名,因此我轉移到了TemporaryFile

def test_invalid_args(self): 
    for args in [['-id', '123456789.00'], ['-i'], ['-i', '0'], ['-i', '../some_invalid_path/not_exist.json']]: 
     with RedirectedEnv(stderr=tempfile.TemporaryFile()): 
      try: 
       self.parser.parse(args) 
       raise AssertionError("should have failed") 
      except Exception: 
       sys.stderr.seek(0) 
       self.assertTrue(sys.stderr.readline().startswith("usage:")) 
+0

謝謝,那正是我想要的。緊湊和富有表現力的,imho。 – Constantine