2016-11-13 2 views
0

В тесте я перенаправил stderr в файл и попытался прочесть его хвостовым способом. Так вот Перенаправление:Python tail-like file read

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 

Есть некоторые элегантный способ сделать это? (Не путайте с enumerate и tell() с seek()) Может быть, есть FIFO queue с файловым интерфейсом?

+0

Исправить отступ в определении класса – Leva7

+0

Почему «искать» беспорядочно? Не следует ли «try» обрезать файл в каждом цикле и не должно ли исключение искать в начале файла и читать строку? Ваш тестовый пример немного странный, поскольку он ловит все исключения, но, похоже, не делает различий между тем, когда список опций должен вызывать исключение, а когда это не должно. Проходят ли некоторые из этих тестов, а другие терпят неудачу? – tdelaney

+0

Все должно потерпеть неудачу. Я издевался над sys.exit, чтобы предотвратить переход от переводчика, чтобы проверить правильность использования сообщения. Возможно, это не лучший способ). Я открыл файл с помощью «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