Как издеваться над атрибутами класса с помощью 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

Когда я пытаюсь издеваться над собственным атрибутом под названием «stdout» (используя pytest),

def return_stdout(*args, **kwargs):
    stdout = "\n\rSome return value\n\r"
    return stdout
monkeypatch.setattr(Upgrade, 'stdout', return_stdout)

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

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

Затем, как я могу издеваться над «stdout», используя pytest или pytest-mock?


person Shirantha Madusanka    schedule 01.09.2020    source источник
comment
класс не имеет атрибута, вы устанавливаете a как переменную экземпляра. Если вы хотите издеваться над ним для класса, сначала объявите его там (class MyClass: \n a = None \n def __init__(... , но тогда конструктор все равно переопределит значение позже. Чего вы пытаетесь достичь?   -  person yedpodtrzitko    schedule 01.09.2020
comment
На самом деле мне нужно протестировать функцию 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): for line in self.stdout: logging.info(str(line)) if str(line).startswith(PLAY RECAP): # сделать что-нибудь   -  person Shirantha Madusanka    schedule 01.09.2020
comment
пожалуйста, добавьте код в исходный вопрос, где его можно отформатировать/выделить, а не так.   -  person yedpodtrzitko    schedule 01.09.2020
comment
Вопрос обновлен   -  person Shirantha Madusanka    schedule 01.09.2020


Ответы (1)


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

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)
person yedpodtrzitko    schedule 01.09.2020