Как имитировать атрибуты класса с помощью pytest

#python #python-3.x #pytest #pytest-mock

#python #python-3.x #pytest #pytest-макет

Вопрос:

У меня есть класс, похожий на этот.

 class Upgrade:

    def __init__(self, ssh_client):
        self.ssh_client = ssh_client
        self.channel = self.ssh_client.invoke_shell(width=1000, height=1000)
        self.stdin = self.channel.makefile('wb')
        self.stdout = self.channel.makefile('r')


    def do_upgrade(self):

        # execute some commands on paramiko channel

        for line in self.stdout:
            
            if str(line).startswith("PLAY RECAP"):
                
                # do something
  

Когда я пытаюсь имитировать атрибут self, называемый ‘stdout’, вот так (используя pytest),

 def return_stdout(*args, **kwargs):
    stdout = "nrSome return valuenr"
    return stdout
monkeypatch.setattr(Upgrade, 'stdout', return_stdout)
  

Я получаю следующую ошибку.

 >     monkeypatch.setattr(Upgrade, 'stdout', return_stdout)
E     AttributeError: <class 'Upgrade'> has no attribute 'stdout'
        
  

Тогда, как я могу имитировать ‘стандартный вывод’, используя pytest или pytest-mock?

Комментарии:

1. у класса нет атрибута, который вы устанавливаете a как переменную экземпляра . Если вы хотите издеваться над ним для класса, сначала объявите его там ( class MyClass: n a = None n def __init__(... , но тогда конструктор все равно переопределит значение позже. Чего вы пытаетесь достичь?

2. На самом деле мне нужно протестировать функцию do_upgrade. обновление класса: def __init__(self, ssh_client): self.ssh_client = ssh_client self.channel = self.ssh_client.invoke_shell(width= 1000, height = 1000) self.stdin = self.channel.makefile(‘wb’) self.stdout = self.channel.makefile(‘r’) def do_upgrade(self): для строки в self. стандартный вывод: logging.info (str(строка)) если str(строка).startswith(«ВОСПРОИЗВЕСТИ КРАТКОЕ ИЗЛОЖЕНИЕ»): # сделай что-нибудь

3. пожалуйста, добавьте код к исходному вопросу, где его можно отформатировать / выделить, а не так.

4. Вопрос обновлен

Ответ №1:

у класса нет атрибута, который вы устанавливаете stdout как переменную экземпляра. И даже если бы вы издевались над ним, вы бы перезаписали его в конструкторе ( self.stdout = self.channel.makefile('r') ). Создайте оболочку / свойство и замените ее на monkeypatch:

 class Upgrade:
    def __init__(self, ssh_client):
        self._stdout = self.channel.makefile('r')

    def get_stdout(self):
        return self._stdout
  

затем в тесте имитируйте метод инкапсуляции вместо этого:

 monkeypatch.setattr(Upgrade, 'get_stdout', return_stdout)