2

我正在设置一个可配置的 SSH 存根 shell,类似于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>>>...' 版本的输出(至少在我通过设置自定义提示符将其中断之前)还是尝试覆盖 shell 提示符以获得干净的输出。

4

1 回答 1

1

很好的问题;感谢您的提问(感谢您使用 Twisted 并使用 TDD :-))。

HistoricRecvLine是一个TerminalProtocol,它提供ITerminalProtocol. ITerminalProtocol.makeConnection必须使用ITerminalTransport. 另一方面,您的单元测试ShellProtocol.makeConnection使用 的实例调用您,该实例StringTransport仅提供IConsumerIPushProducerITransport

由于ShellProtocol.makeConnection期望一个ITerminalTransport,它期望它可以调用它的所有方法。不幸的是,LEFT_ARROW 没有正式记录在这个接口上,这是一个疏忽,但是 Twisted 中这个接口的提供者也提供了这个属性。

你想要做的是将 a 包裹ServerProtocol在你的周围ITerminalProtocol,在这个过程中它将作为你的ITerminalTransport. 您可以在 中查看此组合的一个简单示例twisted.conch.stdio

于 2015-08-08T00:22:33.823 回答