Пробная витая пробка TDD, "экземпляр StringTransport не имеет атрибута..."

Я работаю над настройкой настраиваемой оболочки-заглушки SSH, аналогичной MockSSH, и хочу сделать это на тестовой основе.

Я сталкиваюсь с проблемами тестирования, когда я использую conch.recvline.HistoricRecvLine вместо базового twisted.internet.protocol.Protocol

# test.py
from twisted.trial import unittest
from twisted.test.proto_helpers import StringTransportenter code here

class ShellTest(unittest.TestCase):
    def setUp(self):
        shell_factory = StubShell.ShellFactory()
        self.shell = shell_factory.buildProtocol(('127.0.0.1', 0))
        self.transport = StringTransport()
        self.shell.makeConnection(self.transport)

    def test_echo(self):
        self.shell.lineReceived('irrelevant')
        self.assertEqual(self.transport.value(), 'something')

# shell.py
from twisted.internet import protocol

class ShellProtocol(HistoricRecvLine):

    def connectionMade(self):
        HistoricRecvLine.connectionMade(self)

    def lineReceived(self, line):
        self.terminal.write('line received')

class ShellFactory(protocol.Factory):
    protocol = ShellProtocol

Это работает так, как и ожидалось. Однако, когда я делаю изменения:

class ShellProtocol(HistoricRecvLine):

Я получаю ошибку:

exceptions.AttributeError: StringTransport instance has no attribute 'LEFT_ARROW'

СЛЕДУЮЩИЙ ШАГ: Благодаря помощи Glyph я продвинулся немного дальше, все еще пытаясь настроить тест с минимальными требованиями, чтобы убедиться, что я правильно настраиваю протокол HistoricRecvLine. Я украл некоторый код из test_recvline.py, который все еще кажется мне немного волшебным, особенно установив sp.factory = self(unittest.Testcase). Я пытался свести его к минимуму, чтобы пройти этот тест.

class ShellTestConch(unittest.TestCase):

def setUp(self):
    self.sp = insults.ServerProtocol()
    self.transport = StringTransport()
    self.my_shell = StubShell.ShellProtocol()
    self.sp.protocolFactory = lambda: self.my_shell
    self.sp.factory = self
    self.sp.makeConnection(self.transport)

что приближает меня к ожидаемому результату, однако теперь я вижу, что Терминал сильно искажает вывод, что и следовало ожидать.

twisted.trial.unittest.FailTest: '\x1bc>>> \x1b[4hline received' != 'line received'

В целях TDD я не уверен, должен ли я просто принять версию вывода "\x1bc>>>..." (по крайней мере, пока я не сломаю ее, установив настраиваемое приглашение) или попытаться перезаписать приглашение оболочки на получить чистый вывод.

1 ответ

Решение

Отличный вопрос; спасибо за вопрос (и спасибо за использование Twisted и выполнение TDD:-)).

HistoricRecvLine это TerminalProtocol, который обеспечивает ITerminalProtocol, ITerminalProtocol.makeConnection должен быть вызван с поставщиком ITerminalTransport, С другой стороны, ваш тестовый модуль вызывает ваш ShellProtocol.makeConnection с экземпляром StringTransport, который обеспечивает только IConsumer, IPushProducer, а также ITransport,

поскольку ShellProtocol.makeConnection ожидает ITerminalTransport, он ожидает, что он может вызвать все свои методы. К несчастью, LEFT_ARROW официально не задокументировано для этого интерфейса, что является недосмотром, но поставщики этого интерфейса в Twisted также предоставляют этот атрибут.

Что вы хотите сделать, это обернуть ServerProtocol вокруг вашего ITerminalProtocol, который в процессе будет служить вашим ITerminalTransport, Вы можете увидеть простой пример этой композиции в twisted.conch.stdio,

Другие вопросы по тегам